bug#81538: 32.0.50; Eglot: Non-local exit during window/showDocument handling

Troy Brown via "Bug reports for GNU Emacs, the Swiss army knife of text editors" <[email protected]>
Newsgroups gmane.emacs.bugs
Message-ID <CABvCZ432uPPiEsHP1XkhvOBUX1iL-1buj9H1jLH8amYatK-AOQ@mail.gmail.com>
On Thu, Aug 6, 2026 at 5:46 AM João Távora <[email protected]> wrote:
>
> OK, thanks.  I think I understood what happens, and it can be summarized
> in two lines.
>
> "Using Eglot with the Ada server and my own major mode.  Typing 'M-x
> foo' to jump to bar.ada mostly works, but bar.ada's Eglot is broken :-("

Yes, roughly that is a valid description.

> > This modified ERT test for my major mode exhibits the problem on my
> > machine quite often.
>
> Wait, but does it also happens interactively right?  Or does it _only_
> happen in ERT tests?

Yes, it absolutely happens interactively.  The command is bound to C-c
C-o in the major mode and interactive use is where the problem was
discovered.  I modified an existing test to try and create a
reproducible scenario with larger files, enabled traces and output of
the Eglot event log.

> In other words, you seem to be describing these 5 events
>
> a1. -> adals/ff-thingy sync client request (eglot-execute-command, interactive, from user)
> b1.   <- window/showDocument server request
> c.      -> f-f-no-select, Eglot sends the large didOpen notification
> b2.   -> window/showDocument client response
> a2. <- ada/ff-thingy server response
>
> And your description is that in certain situations ('a2' is sitting in
> the pipes ready to go early and 'c' is reasonably large), 'a2' is
> processed ahead of time, and the ensuing 'throw' causes important steps
> near 'c' to be skipped.  I agree that this would indeed be problematic.
> But Eglot's method:
>
>    (cl-defmethod eglot-handle-request (_server (_method (eql
>    window/showDocument))
>
> has a provision to execute 'c' in a "run-with-timer 0".  Put
> differently, the intent here is "agree what to do, finish the
> transaction, only then go to the thing"".  So the intended sequence of
> events should in theory, be:
>
> a1. -> adals/ff-thingy sync client request (eglot-execute-command, interactive, from user)
> b1.   <- window/showDocument server request
> b2.   -> window/showDocument client response
> a2. <- ada/ff-thingy server response
> c.  -> f-f-no-select, Eglot sends the large didOpen notification
>
> Except, according to your observations, it is not....

I don't think `a2` arrives early, I think it is triggered by the
server having received `b2` (which is transmitted prior to the
processing of `c` as you've noted above).  Looking at the Eglot event
logs shows about 50ms between when `b2` is sent and when `a2` arrives.
During this 50ms window is when I believe the timer which contains`c`
starts to be processed by Emacs.

> I will look into this some more from the jsonrpc.el side, but can you
> try this silly patch and see if the problem goes away?
>
> @@ -2965,7 +2965,7 @@ eglot-handle-request
>        ;; "synchronous imenu" floated in bug#62116 presumably caused by
>        ;; which-func-mode.
>        (run-with-timer
> -       0 nil
> +       0.1 nil
>         (lambda ()
>           (with-current-buffer (find-file-noselect filename)
>             (cond (takeFocus

Yes, this patch does seem to fix the problem...at least I couldn't
reproduce it after applying it.  I believe the 100ms delay ensures
that `a2` is received prior to starting to process `c`, at least on my
machine.

I think the interesting thing to note are the traces in the attached
trace log in the original email.  Looking at nested traced function
call #15 (jsonrpc-connection-send) and #17
(jsonrpc-connection-receive) shows that there is a way to receive data
while the transmission of data has not yet completed, which correlates
to the reception of `a2` while in the middle of sending the large `c`.


Troy.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.