Subject: Re: bug#49954: 28.0.50; TRAMP: cannot kill child processes: "Forbidden reentrant call of Tramp"

From: Michael Albinus <[email-masked]>
Date: Sat, 11 Sep 2021 14:19:06 +0200

Dima Kogan <[email-masked]> writes:

> Hi Michael.

Hi Dima,

> So I've seen this a number of times now, and it really looks like the
> caching mechanism is the problem.

No, it isn't. Tramp uses its cache just as memory. The problem is
somewhere else, see below.

> Every time I see "Forbidden reentrant call of Tramp" when trying to
> C-c C-c a remote process, I re-evaluate tramp-get-connection-property
> with
>
>   (when (and (not (eq cached tramp-cache-undefined))
>              ;; If the key is an auxiliary process object, check
>              ;; whether the process is still alive.
>              (not (and (processp key) (not (process-live-p key)))))
>     (setq value cached
>           cache-used t))
>
> removed. This effectively disables the caching mechanism. Then I can C-c
> C-c my process, and it dies like it's supposed to. TRAMP feels slower
> after than, as expected, so I put tramp-get-connection-property back to
> what it was. Eventually the problem comes back, and I do the same dance
> to "fix" it.

The Tramp manual tells you how to bypass the problem, see Frequently
Asked Questions:

--8<---------------cut here---------------start------------->8---
   • I get an error ‘Remote file error: Forbidden reentrant call of
     Tramp’

     Timers, process filters and sentinels, and other event based
     functions can run at any time, when a remote file operation is
     still running.  This can cause TRAMP to block.  When such a
     situation is detected, this error is triggered.  It should be fixed
     in the respective function (sending an error report will help), but
     for the time being you can suppress this error by the following
     code in your ‘~/.emacs’:

          (setq debug-ignored-errors
                (cons 'remote-file-error debug-ignored-errors))
--8<---------------cut here---------------end--------------->8---

In order to understand the problem, let's assume the following scenario:

- You have connected to a remote host, say "/ssh:host:". Tramp uses
  internally the process *tramp/ssh host* for communicating with that
  process.

- You have also started another asynchronous process to that remote
  host.

- Now, while normal use of Emacs, the function (file-attributes
  "/ssh:host:/path/to/file") is called. Tramp sends a command to the
  process *tramp/ssh host*, like "stat /path/to/file".

- While Tramp waits for the answer of the "stat ..." command, your other
  process has finished. It might have a process sentinel, which is
  called exactly at this time, because Tramp is in a loop
  (accept-process-output ...).

- This process filter might trigger another file operation, like
  (delete-file "/ssh:host:/tmp/tmpfile"). This would require to send
  another command to the *tramp/ssh host* process like "rm -f /tmp/tmpfile".

- Since the first command, "stat ...", hasn't been finished, this would
  result in inconsistencies. Tramp detects this situation, and raises
  the "Forbidden reentrant call of Tramp" error.

Not so easy to solve. Ideally, remote file name functions initiated in
process filters, process sentinels, timers and alike shall wait, until
the currently executed remote command has finished. Don't know how to
achieve this.

Best regards, Michael.