|
From: Bob R. <rog...@rg...> - 2003-12-21 03:38:11
|
This syndrome turns out to be due to a particular series of events
that exposes a comint-process-filter flaw. The key requirement is that
the response be broken into at least two chunks, resulting in two calls
to comint-process-filter. Here's what's happening in detail:
1. emacs queries the lisp for definitions. This amounts to sending
the query string, and doing accept-process-output until a reponse comes
back.
2. The lisp responds, but not fully, due to buffering. The partial
response must contain the complete Lisp response sexp, but must not
include the prompt. This allows M-. to continue while the Lisp is still
sending output.
3. Back in emacs, the process filter changes from the current buffer
(where you typed M-.), updates data structures to pass the result back
to M-., and restores the current buffer.
4. The query returns, and the caller takes the response, builds the
*Edit-Definitions* buffer, and goes to work on it. When it gets to a
comment in *Edit-Definitions*, it does sit-for, which allows process
filters to run.
5. When the process filter is called the second time, the current
buffer is initially *Edit-Definitions*, which was installed temporarily
via set-buffer (rather than switch-to-buffer), so it isn't visible in
any window. For that dubious reason, the following fragment at the end
of comint-process-filter decides not to restore the current buffer:
(if (or (get-buffer-window comint-original-buffer)
(eq (window-buffer (minibuffer-window)) comint-original-buffer))
(set-buffer comint-original-buffer))))
6. The sit-for returns, and lisp-find-next-possibility comes up
empty-handed, because it's looking in the Lisp buffer instead of
*Edit-Definitions*.
7. On exit from lisp-find-next-possibility, the initial current
buffer (where M-. was typed) is restored, neatly hiding the problem.
I can't imagine what the point of the conditional buffer restore
could be. It's not doing "switch to buffer on output," because we may
not have actually generated any output -- and in the case of M-., we see
that it is doomed to fail anyway.
In addition to doing set-buffer unconditionally in the patch I just
committed, I also wrapped the whole thing in an unwind-protect, since
that's the only way to get emacs to clean up for us if the process
filter encounters an error. Figuring out the timing requirements made
this error symptom 100% repeatable (sometimes it helps to have a slow
machine), so I am pretty confident of this fix, despite lack of
comint-ipc experience. Let me know if you see any problems.
-- Bob Rogers
http://rgrjr.dyndns.org/
|