Package: emacs;
View this message in rfc822 format
From: Michael Albinus <michael.albinus <at> gmx.de> To: João Távora <joaotavora <at> gmail.com> Cc: Thomas Koch <thomas <at> koch.ro>, 61350 <at> debbugs.gnu.org Subject: bug#61350: Eglot over Tramp freezes with large project Date: Thu, 02 Mar 2023 12:01:32 +0100
João Távora <joaotavora <at> gmail.com> writes: Hi João, > But JUST-THIS-ONE _is_ relevant when there is more than one process. > Here, there is. There's one process, the jsonrpc.el process, henceforth > 'jprocess', and the Tramp process, henceforth 'tprocess'. jprocess > receives only JSONRPC data from the LSP server. It "thinks" it is > talking directly to a JSONRPC server, but in Tramp scenarios it is being > fed data from tprocess, which is the process connected to the remote > host. In tprocess, other things, such as shell interactions are going > on. > > Michael can probably confirm, correct or deny this. More or less correct. But I still can't say which process gets output when, because I cannot debug accept-process-output (it's a C function). And running Emacs under gdb changes timings, which is important I believe. > When one (accept-process-output tprocess nil nil 'JUST-THIS-ONE=t) one > must be absolutely sure that tprocess is going to send _something_ > "soon". If it doesn't, we'll hang indefinitely (until the process dies > or the user quits) Yes. But Tramp calls accept-process-output only, if it has send a command to the remote shell, and it expects something to be returned. At least the shell prompt. During my tests I have also changed this to --8<---------------cut here---------------start------------->8--- (while (accept-process-output tprocess 0 nil 'JUST-THIS-ONE)) --8<---------------cut here---------------end--------------->8--- but it didn't help either. > That's what has been confirmed through a backtrace. It's a particular > accept-process-output call in tramp-wait-for-regexp that hangs, > understandibly so. Yes. > Now, 'tramp-check-for-regexp' uses a somewhat non-standard technique of > searching for messages: it searches them from the back, from the end of > the tprocess's buffer. I don't know what motivated this, but I find it > odd. I find one of its callees, tramp-search-regexp, particularly > suspicious: > > (defun tramp-search-regexp (regexp) > "Search for REGEXP backwards, starting at point-max."" > (goto-char (point-max)) > ;; We restrict ourselves to the last 256 characters. There were > ;; reports of a shell command "git ls-files -zco --exclude-standard" > ;; with 85k files involved, which has blocked Tramp forever. > (re-search-backward regexp (max (point-min) (- (point) 256)) 'noerror)) > > See the comment there? Only 256 characters back are inspected. Yes. But the regexp it searches for is the final shell prompt. Something like "///4b3b7d4fa561141e84c94a1cf25e8575#$", which is shorter than 256 bytes for sure. > So, finally, here's my conjecture: > > 1. Tramp goes into 'tramp-wait-for-regexp'. tprocess's buffer already > the message that 'found' is supposed to return, but it also has a lot > more stuff, say a lot of JSONRPC data from the LSP server that also > came into that tprocess buffer and is awaiting to be delivered to > jprocess. > > 2. This data is for piping into jprocess, where the JSONRPC message will > be decoded, but it will probably never arrive at its destination. > > 3. 'found' will be nil in tramp-wait-for-regexp, because of the > tramp-search-regexp limitation. > > 4. tramp-wait-for-regexp will issue the "risky" accept-process-output > call. > > 5. there is no more data that accept-process-output wants to put in the > buffer, because the LSP server is fine for the moment. > > 6. Emacs hang > > Just a conjecture. Yes, this is more or less the scenario. But I still don't understand why not all data are delivered through the socket ssh is using. Could it be there is a limitation, how much data could be buffered by ssh? >> I have a vague feeling, that Tramp could be improved with a work queue >> such that requests to tramp from notification or timer threads get >> blocked while another tramp command is still waiting for a >> reply. > > There are no (usable) threads in Emacs. There are. I made Tramp using threads, and it worked fine, when no interactive dialogue inside a thread happened. > Timers are events, and so are runs of each processe's process filter. > Those two are what creates asynchronicity and the emulation of > simultaneity in Emacs. When jprocess's filter sees a whole JSONRPC > message, it calls the message handler. Timers and process filters are the cause of the "Forbidden reentrant call in Tramp" errors. Wwe must do anything, solving this. > João Best regards, Michael.
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.