Subject: Re: bug#34192: 26.1; Bash 5.0 breaks TRAMP sudo

From: Allen Li <[email-masked]>
Date: Tue, 29 Jan 2019 05:48:49 +0000

On Mon, Jan 28, 2019 at 9:12 AM Michael Albinus <[email-masked]> wrote:
>
> Allen Li <[email-masked]> writes:
>
> Hi Allen,
>
> > I get tramp_exit_status 0 as expected, but I think
> > tramp_perl_file_name_all_completions may be a red herring, since when
> > I tried using Edebug on tramp-sh-handle-file-name-all-completions, I
> > get the "Process has died" error after some time irrespective of my
> > code stepping.
>
> So could you pls call this shell function, once it has been declared:
>
> # tramp_perl_file_name_all_completions `pwd`

Running that didn't yield any insights. in both normal bash and bash
--posix.  I also tried sending it via stdin instead of an interactive
shell, all with no luck.

I tried monkey patching tramp-wait-for-regexp to see what the exit status is.

(defun tramp-wait-for-regexp (proc timeout regexp)
  "Wait for a REGEXP to appear from process PROC within TIMEOUT seconds.
Expects the output of PROC to be sent to the current buffer.  Returns
the string that matched, or nil.  Waits indefinitely if TIMEOUT is
nil."
  (with-current-buffer (process-buffer proc)
    (let ((found (tramp-check-for-regexp proc regexp)))
      (cond (timeout
     (with-timeout (timeout)
       (while (not found)
(tramp-accept-process-output proc 1)
(unless (process-live-p proc)
                   (message "@@@@@@@@@@@ DEAD %d" (process-exit-status proc))
                   (debug)
   (tramp-error-with-buffer
    nil proc 'file-error "Process has died"))
(setq found (tramp-check-for-regexp proc regexp)))))
    (t
     (while (not found)
       (tramp-accept-process-output proc 1)
       (unless (process-live-p proc)
                 (message "@@@@@@@@@@@ DEAD %d" (process-exit-status proc))
                 (debug)
(tramp-error-with-buffer
  nil proc 'file-error "Process has died"))
       (setq found (tramp-check-for-regexp proc regexp)))))
      (tramp-message proc 6 "\n%s" (buffer-string))
      (when (not found)
(if timeout
    (tramp-error
     proc 'file-error "[[Regexp `%s' not found in %d secs]]"
     regexp timeout)
  (tramp-error proc 'file-error "[[Regexp `%s' not found]]" regexp)))
      found)))

In my Messages buffer, I found

@@@@@@@@@@@ DEAD 139

A search tells me that this is SIGSEGV.

The corresponding backtrace:

  (if (process-live-p proc) nil (message "@@@@@@@@@@@ DEAD %d"
(process-exit-status proc)) (debug) (tramp-error-with-buffer nil proc
'file-error "Process has died"))
  (while (not found) (tramp-accept-process-output proc 1) (if
(process-live-p proc) nil (message "@@@@@@@@@@@ DEAD %d"
(process-exit-status proc)) (debug) (tramp-error-with-buffer nil proc
'file-error "Process has died")) (setq found (tramp-check-for-regexp
proc regexp)))
  (cond (timeout (let ((-with-timeout-value- (catch 'timeout (let*
((-with-timeout-timer- (run-with-timer timeout nil (function (lambda
nil (throw 'timeout 'timeout))))) (with-timeout-timers (cons
-with-timeout-timer- with-timeout-timers))) (unwind-protect (progn
(while (not found) (tramp-accept-process-output proc 1) (if
(process-live-p proc) nil (message "@@@@@@@@@@@ DEAD %d"
(process-exit-status proc)) (debug) (tramp-error-with-buffer nil proc
'file-error "Process has died")) (setq found (tramp-check-for-regexp
proc regexp)))) (cancel-timer -with-timeout-timer-)))))) (if (eq
-with-timeout-value- 'timeout) (progn) -with-timeout-value-))) (t
(while (not found) (tramp-accept-process-output proc 1) (if
(process-live-p proc) nil (message "@@@@@@@@@@@ DEAD %d"
(process-exit-status proc)) (debug) (tramp-error-with-buffer nil proc
'file-error "Process has died")) (setq found (tramp-check-for-regexp
proc regexp)))))
  (let ((found (tramp-check-for-regexp proc regexp))) (cond (timeout
(let ((-with-timeout-value- (catch 'timeout (let*
((-with-timeout-timer- (run-with-timer timeout nil (function (lambda
nil (throw 'timeout 'timeout))))) (with-timeout-timers (cons
-with-timeout-timer- with-timeout-timers))) (unwind-protect (progn
(while (not found) (tramp-accept-process-output proc 1) (if
(process-live-p proc) nil (message "@@@@@@@@@@@ DEAD %d"
(process-exit-status proc)) (debug) (tramp-error-with-buffer nil proc
'file-error "Process has died")) (setq found (tramp-check-for-regexp
proc regexp)))) (cancel-timer -with-timeout-timer-)))))) (if (eq
-with-timeout-value- 'timeout) (progn) -with-timeout-value-))) (t
(while (not found) (tramp-accept-process-output proc 1) (if
(process-live-p proc) nil (message "@@@@@@@@@@@ DEAD %d"
(process-exit-status proc)) (debug) (tramp-error-with-buffer nil proc
'file-error "Process has died")) (setq found (tramp-check-for-regexp
proc regexp))))) (tramp-message proc 6 "\n%s" (buffer-string)) (if
(not found) (progn (if timeout (tramp-error proc 'file-error "[[Regexp
`%s' not found in %d secs]]" regexp timeout) (tramp-error proc
'file-error "[[Regexp `%s' not found]]" regexp)))) found)
  (save-current-buffer (set-buffer (process-buffer proc)) (let ((found
(tramp-check-for-regexp proc regexp))) (cond (timeout (let
((-with-timeout-value- (catch 'timeout (let* ((-with-timeout-timer-
(run-with-timer timeout nil (function (lambda nil (throw 'timeout
'timeout))))) (with-timeout-timers (cons -with-timeout-timer-
with-timeout-timers))) (unwind-protect (progn (while (not found)
(tramp-accept-process-output proc 1) (if (process-live-p proc) nil
(message "@@@@@@@@@@@ DEAD %d" (process-exit-status proc)) (debug)
(tramp-error-with-buffer nil proc 'file-error "Process has died"))
(setq found (tramp-check-for-regexp proc regexp)))) (cancel-timer
-with-timeout-timer-)))))) (if (eq -with-timeout-value- 'timeout)
(progn) -with-timeout-value-))) (t (while (not found)
(tramp-accept-process-output proc 1) (if (process-live-p proc) nil
(message "@@@@@@@@@@@ DEAD %d" (process-exit-status proc)) (debug)
(tramp-error-with-buffer nil proc 'file-error "Process has died"))
(setq found (tramp-check-for-regexp proc regexp))))) (tramp-message
proc 6 "\n%s" (buffer-string)) (if (not found) (progn (if timeout
(tramp-error proc 'file-error "[[Regexp `%s' not found in %d secs]]"
regexp timeout) (tramp-error proc 'file-error "[[Regexp `%s' not
found]]" regexp)))) found))
  tramp-wait-for-regexp(#<process *tramp/sudo root@cielnosurge*> nil
"\\(^\\|\0\\)[^#$\n]*///e7c116e27b816fdfc1b43f2c9e5a951b#\\$\\(\033[[0-9]+n\\)?\015?$")
  tramp-wait-for-output(#<process *tramp/sudo root@cielnosurge*>)
  tramp-send-command((tramp-file-name "sudo" #("root" 0 4
(tramp-default t)) nil "cielnosurge" nil "/" nil)
"tramp_perl_file_name_all_completions () {\n\\perl -e '\nopendir(d,
$ARGV[0]) || die(\"$ARGV[0]: $!\\nfail\\n\");\n@files = readdir(d);
closedir(d);\nforeach $f (@files) {\n if (-d \"$ARGV[0]/$f\") {\n
print \"$f/\\n\";\n }\n else {\n  print \"$f\\n\";\n }\n}\nprint
\"ok\\n\"\n' \"$1\" 2>/dev/null\n} 2>/dev/null; echo tramp_exit_status
$?")
  tramp-send-command-and-check((tramp-file-name "sudo" #("root" 0 4
(tramp-default t)) nil "cielnosurge" nil "/" nil)
"tramp_perl_file_name_all_completions () {\n\\perl -e '\nopendir(d,
$ARGV[0]) || die(\"$ARGV[0]: $!\\nfail\\n\");\n@files = readdir(d);
closedir(d);\nforeach $f (@files) {\n if (-d \"$ARGV[0]/$f\") {\n
print \"$f/\\n\";\n }\n else {\n  print \"$f\\n\";\n }\n}\nprint
\"ok\\n\"\n' \"$1\" 2>/dev/null\n}")
  tramp-barf-unless-okay((tramp-file-name "sudo" #("root" 0 4
(tramp-default t)) nil "cielnosurge" nil "/" nil)
"tramp_perl_file_name_all_completions () {\n\\perl -e '\nopendir(d,
$ARGV[0]) || die(\"$ARGV[0]: $!\\nfail\\n\");\n@files = readdir(d);
closedir(d);\nforeach $f (@files) {\n if (-d \"$ARGV[0]/$f\") {\n
print \"$f/\\n\";\n }\n else {\n  print \"$f\\n\";\n }\n}\nprint
\"ok\\n\"\n' \"$1\" 2>/dev/null\n}" "Script %s sending failed"
"tramp_perl_file_name_all_completions")
  tramp-maybe-send-script((tramp-file-name "sudo" #("root" 0 4
(tramp-default t)) nil "cielnosurge" nil "/" nil) "%s -e '\nopendir(d,
$ARGV[0]) || die(\"$ARGV[0]: $!\\nfail\\n\");\n@files = readdir(d);
closedir(d);\nforeach $f (@files) {\n if (-d \"$ARGV[0]/$f\") {\n
print \"$f/\\n\";\n }\n else {\n  print \"$f\\n\";\n }\n}\nprint
\"ok\\n\"\n' \"$1\" 2>/dev/null"
"tramp_perl_file_name_all_completions")
  tramp-sh-handle-file-name-all-completions(""
#("/sudo:root@cielnosurge:/" 6 10 (tramp-default t)))
  apply(tramp-sh-handle-file-name-all-completions (""
#("/sudo:root@cielnosurge:/" 6 10 (tramp-default t))))
  tramp-sh-file-name-handler(file-name-all-completions ""
#("/sudo:root@cielnosurge:/" 6 10 (tramp-default t)))
  apply(tramp-sh-file-name-handler file-name-all-completions (""
#("/sudo:root@cielnosurge:/" 6 10 (tramp-default t))))
  tramp-file-name-handler(file-name-all-completions ""
#("/sudo:root@cielnosurge:/" 6 10 (tramp-default t)))
  file-name-all-completions("" #("/sudo:root@cielnosurge:/" 6 10
(tramp-default t)))
  tramp-handle-file-name-completion("" #("/sudo:root@cielnosurge:/" 6
10 (tramp-default t)) file-exists-p)
  apply(tramp-handle-file-name-completion (""
#("/sudo:root@cielnosurge:/" 6 10 (tramp-default t)) file-exists-p))
  tramp-sh-file-name-handler(file-name-completion ""
#("/sudo:root@cielnosurge:/" 6 10 (tramp-default t)) file-exists-p)
  apply(tramp-sh-file-name-handler file-name-completion (""
#("/sudo:root@cielnosurge:/" 6 10 (tramp-default t)) file-exists-p))
  tramp-file-name-handler(file-name-completion ""
#("/sudo:root@cielnosurge:/" 6 10 (tramp-default t)) file-exists-p)

>
> Instead of `pwd` you could use any directory path.
>
> Best regards, Michael.