Subject: bug#61350: Eglot over Tramp freezes with large project

From: Michael Albinus <[email-masked]>
Date: Tue, 07 Mar 2023 13:49:31 +0100

Michael Albinus <[email-masked]> writes:

Hi Thomas & João,

before going offline just a short status update.

>> However my conclusion is different. I consider the root-cause to be
>> the use of JUST-THIS-ONE in tramps call to
>> accept-process-output. Please check my comment to bug
>> https://debbugs.gnu.org/cgi/bugreport.cgi?bug=12145
>
> I've seen this. And yes, we shall fix the problems described there.
>
>> As a practical roadmap you could add an option to Tramp to disable
>> JUST-THIS-ONE and recommend its use. Later the options default could
>> be toggled. Eventually the option can go away.
>
> Might be applicable in the master branch. But first we need much more
> checks that it doesn't break something else.
>
> I'm always uncomfortable to change Tramp such a way that other packages
> could be broken. Letting Tramp accept process output for all existing
> processes doesn't seem to be the right thing to me, although I admit
> that it seems to fix the specific problem we're discussing here.

Thinking about, I came to a less invasive idea: Just the processes which
possibly use the same socket for the ssh connection should accept their
output in time. This avoids to change the behavior of other processes,
which are not related to a given Tramp connection. And it makes me feel
much better :-)

The small patch below, on top of Tramp 2.6.0.2, seems to fix the
problem. I've also deactivated (in Emacs 29) João's Tramp fix, and I've
applied the recipe given by Thomas 10 times in a row, always starting
with "emacs -Q ...". 10 times success.

Could you please check how it works in your environment? You'll have
some days until I'll be back. If it also works for you, I will add it to
Tramp 2.6.0.3, and we could close this bug.

For completeness, tramp-test44-asynchronous-requests now fails in
tramp-tests.el. But this test is already flaky (not passing successfully
every time), so I'll investigate later what's up with this.

Best regards, Michael.

diff --git a/lisp/tramp.el b/lisp/tramp.el
index 24b7c45d..50945ccb 100644
--- a/lisp/tramp.el
+++ b/lisp/tramp.el
@@ -5746,6 +5746,17 @@ Mostly useful to protect BODY from being interrupted by timers."
 This is needed in order to hide `last-coding-system-used', which is set
 for process communication also.
 If the user quits via `C-g', it is propagated up to `tramp-file-name-handler'."
+  ;; There could be other processes which use the same socket for
+  ;; communication.  This could block the output for the current
+  ;; process.  Read such output first.  (Bug#61350)
+  ;; If `timeout' is nil, `accept-process-output' for `proc' could
+  ;; block another such a process.  So we set `timeout' to 0 then.
+  (dolist (p (delq proc (process-list)))
+    (when (tramp-file-name-equal-p
+	   (process-get proc 'vector) (process-get p 'vector))
+      (setq timeout  (or timeout 0))
+      (accept-process-output p 0 nil t)))
+
   (with-current-buffer (process-buffer proc)
     (let ((inhibit-read-only t)
 	  last-coding-system-used