Subject: bug#55832: 28.1; Emacs crashes when using tramp from helm in emacs-29

From: Michael Albinus <[email-masked]>
Date: Fri, 10 Jun 2022 09:53:44 +0200

Eli Zaretskii <[email-masked]> writes:

Hi,

>> > So tramp-file-name-for-operation errors out, and that somehow gets us
>> > in trouble.
>> >
>> > I see we call signal-hook-function -- what is its value in that
>> > session, please?
>>
>> Seems tramp let-bound it to tramp-signal-hook-function in
>> tramp-file-name-handler.
>
> Michael, can you help us out here?  Could the above somehow cause
> infinite recursion, whereby signaling an error triggers another,
> nested error?

First, I've tried to reproduce it from emacs -Q. I've upgraded all
installed ELPA packages, and then I have called

--8<---------------cut here---------------start------------->8---
emacs -Q \
  -l ~/.emacs.d/elpa/helm-core-20220503.622/helm-core-autoloads.el \
  -l ~/.emacs.d/elpa/helm-20220504.827/helm-autoloads.el \
  -l ~/.emacs.d/elpa/helm-tramp-20190616.125/helm-tramp-autoloads.el \
  -l ~/.emacs.d/elpa/async-20220318.1342/async-autoloads.el \
  -l seq -f helm-find-files
--8<---------------cut here---------------end--------------->8---

Using /sudo:: as file name doesn't raise any error. However, this is
from the master branch; Emacs 28 doesn't play fine with the compiled
Helm libraries because of an error in calling string-match (using the
new optional arg INHIBIT-MODIFY). And I don't want to recompile all my
installed packages with Emacs 28. Hmm.

Looking at the error, it comes indeed from
tramp-file-name-for-operation. In the backtrace shown by Thierry it
looks like this function is called for tramp-get-remote-uid:

--8<---------------cut here---------------start------------->8---
(gdb) xsymbol
$5 = (struct Lisp_Symbol *) 0x555558080030
"tramp-file-name-for-operation"
(gdb) p args[1]
$6 = XIL(0x22fdb90)
(gdb) xtype
Lisp_Symbol
(gdb) xsymbol
$7 = (struct Lisp_Symbol *) 0x555557fd47d0
"tramp-get-remote-uid"
--8<---------------cut here---------------end--------------->8---

tramp-get-remote-uid *is* a valid argument, and
tramp-file-name-for-operation shouldn't raise an error. Once we have
fixed the problem of Emacs crash, it shall be investigated wy this error
has been raised.

It is not clear to me why tramp-file-name-for-operation goes into
recursion with the error handling, invoking again and again
tramp-signal-hook-function (that is the function bound to
signal-hook-function). However, a simple protection against this should
be this patch:

diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 3ee1169139..3905aeba70 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -2476,6 +2476,7 @@ tramp-file-name-for-operation
 It does not always return a Tramp file name, for example if the
 first argument of `expand-file-name' is absolute and not remote.
 Must be handled by the callers."
+  (let (signal-hook-function)
   (cond
    ;; FILE resp DIRECTORY.
    ((member operation
@@ -2558,7 +2559,7 @@ tramp-file-name-for-operation
    ((member operation '(tramp-get-remote-gid tramp-get-remote-uid))
     (tramp-make-tramp-file-name (nth 0 args)))
    ;; Unknown file primitive.
-   (t (error "Unknown file I/O primitive: %s" operation))))
+   (t (error "Unknown file I/O primitive: %s" operation)))))

 (defun tramp-find-foreign-file-name-handler (filename &optional _operation)
   "Return foreign file name handler if exists."

Similar protections have been applied already elsewhere in Tramp. Does
this solve the problem?

Best regards, Michael.