bug#81538: 32.0.50; Eglot: Non-local exit during window/showDocument handling
João Távora <[email protected]> Sun, 02 Aug 2026 20:14:46 +0100
| Newsgroups | gmane.emacs.bugs |
|---|---|
| Message-ID | <[email protected]> |
Eli Zaretskii <[email protected]> writes: >> Date: Sun, 2 Aug 2026 14:05:56 -0400 >> From: Troy Brown via "Bug reports for GNU Emacs, >> the Swiss army knife of text editors" <[email protected]> >>=20 >> The Ada Language Server has a command for showing the "other file". >> This is similar to `ff-find-other-file` for navigating between an Ada >> body (similar to C source) file and an Ada specification (similar to C >> header) file. It has advantages over `ff-find-other-file` as it can >> automatically map between files with non-standard naming conventions, >> so it is preferred over `ff-find-other-file`. I trigger this command >> using `eglot-execute-command` which sends a >> `workspace/executeCommand`. When the Language Server command is sent, >> the server responds with a `window/showDocument` request back to Emacs >> to open the corresponding file. Eglot receives this request and >> starts the process of opening the corresponding file (via >> `find-file-noselect`), and sends a response back to the server. OK so far. >> As was noted in Bug#60088, when a string sent to `process-send-string` >> (via `jsonrpc-connection-send`) is large enough, it can cause >> reception of output from the server (likely due to the output buffer >> becoming full, causing output from the server to be processed by >> `jsonrpc-connection-receive` [via `jsonrpc--process-filter`]). "It can cause reception of output"??? That's... good? >> When the eglot package is loaded, it registers >> `eglot--maybe-activate-editing-mode` in the >> `after-change-major-mode-hook`. As part of the `find-file-noselect` >> machinery, these hooks are executed and >> `eglot--maybe-activate-editing-mode` is run. This function executes >> `eglot--signal-textDocument/didOpen` to indicate to the server the new >> document being opened (by sending `textDocument/didOpen` via >> `jsonrpc-connection-send` and ultimtely via `process-send-string`). >> The `textDocument/didOpen` ends up sending the entire buffer contents >> of the new file to the server as part of it's payload. If this file >> is large enough, it can cause the scenario above where the output >> buffer becomes full and it starts processing output from the language >> server. >>=20 >> When Emacs starts processing the output from the server, it ends up >> processing the `workspace/executeCommand` response. This bubbles down >> through `jsonrpc--process-filter`, `jsonrpc-connection-receive` and >> `jsonrpc--continue` where the "success function" is invoked. This >> function is the lambda function setup in `jsonrpc-request` which >> performs a transfer of control via the "throw" in that function. This >> causes a non-local exit and an unwinding all the way back to the >> `jsonrpc-request` from the original `workspace/executeCommand` >> command. This non-local exit prevents the `textDocument/didOpen` from >> completing and prevents the `find-file-noselect` from finishing, >> leaving the buffer incompletedly initialized (e.g., `font-lock` is not >> enabled, etc.) and doesn't end up popping the buffer, so it stays >> hidden. >>=20 >> While I've documented the method by which this problem arises for >> myself, I think this scenario can arise in more generalized scenarios >> where outstanding replies might be received and cause in-progress >> transmissions to be aborted prematurely. I think this might be solved >> by delaying processing of the process output while a send is currently >> in progress. >>=20 >> I have enabled numerous function traces to track this down and provide >> a visible representation of what appears to be happening. The full >> eglot event and trace function logs can be found in the attachments. >> The following illustrates the interesting part of the eglot event log >> to illustrate the client/server communication described above. >>=20 >> ```text >> [jsonrpc] e[10:12:28.254] --> workspace/executeCommand[13] >> {"jsonrpc":"2.0","id":13,"method":"workspace/executeCommand","params":{"= command":"als-other-file","arguments":[{"uri":"file:///home/troy/junk/crate= /gtkada_24.0.0_80c56171/src/gtkada-mdi.adb"}]}} >> [jsonrpc] e[10:12:28.255] <-- window/showDocument[4] >> {"jsonrpc":"2.0","id":4,"method":"window/showDocument","params":{"uri":"= file:///home/troy/junk/crate/gtkada_24.0.0_80c56171/src/gtkada-mdi.ads","ta= keFocus":true}} >> [jsonrpc] e[10:12:28.256] --> window/showDocument[4] >> {"jsonrpc":"2.0","id":4,"result":{"success":true}} >> [jsonrpc] e[10:12:28.313] <-- workspace/executeCommand[13] >> {"jsonrpc":"2.0","id":13,"result":null} >> ``` > > Adding Jo=C3=A3o. Troy, you'll excuse the condescending tone, but this is not the first time I observe this (in fact I see this way too often): you are so caught up in the details of your debugging session that you forgot the basics. Please explain from top-to-bottom, in fact, explain just the problem from the top, period. What do you type/click to make the problem happen? Also Eglot/Emacs versions are missing (at least from Eli'sq forwarded message) And you know what's even better? Explain clearly how to install this language server and setup a reproduction. Read https://joaotavora.github.io/eglot/#Reporting-bugs for ideas. Doing so will increase the chances that someone (maybe be, maybe someone else) will actually look at this and help you solve you'll problem. Later on you can give all the debugging nitty gritty and your text will make more sense. Jo=C3=A3o