From 34c17cd8d61a841dcca4c307bc436b5d09b5a965 Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Wed, 12 Aug 2020 12:45:45 +0200 Subject: [PATCH] Implement Tramp direct async processes fallback for multi-hops * doc/misc/tramp.texi (Remote processes): Precise restrictions for direct async processes. * lisp/net/tramp-adb.el (tramp-adb-handle-make-process): * lisp/net/tramp-sh.el (tramp-sh-handle-make-process): Use `tramp-direct-async-process-p'. * lisp/net/tramp.el (tramp-direct-async-process-p): New defun. (tramp-handle-make-process): Adapt handling of :stderr. Simplify. --- doc/misc/tramp.texi | 19 +++++++++++-------- lisp/net/tramp-adb.el | 3 +-- lisp/net/tramp-sh.el | 3 +-- lisp/net/tramp.el | 33 ++++++++++++++++++++++++--------- 4 files changed, 37 insertions(+), 21 deletions(-) diff --git a/doc/misc/tramp.texi b/doc/misc/tramp.texi index 23221b6a7b8..c1a66d02512 100644 --- a/doc/misc/tramp.texi +++ b/doc/misc/tramp.texi @@ -3561,23 +3561,23 @@ which must be set to a non-@code{nil} value. Example: @end group @end lisp -However, this approach has different limitations: +Using direct asynchronous processes in @value{tramp} is not possible, +if the remote host is connected via multiple hops +(@pxref{Multi-hops}), or the @code{make-process} / +@code{start-file-process} call uses a stderr stream. In this case, +@value{tramp} falls back to its classical implementation. + +Furthermore, this approach has the following limitations: @itemize @item It works only for connection methods defined in @file{tramp-sh.el} and @file{tramp-adb.el}. -@item -It does not support multi-hop methods. - @item It does not support interactive user authentication, like password handling. -@item -It does not support a separated error stream. - @item It cannot be killed via @code{interrupt-process}. @@ -3594,7 +3594,10 @@ It does not set environment variable @env{INSIDE_EMACS}. In order to gain even more performance, it is recommended to bind @code{tramp-verbose} to 0 when running @code{make-process} or -@code{start-file-process}. +@code{start-file-process}. Furthermore, you might set +@code{tramp-use-ssh-controlmaster-options} to @code{nil} in order to +bypass @value{tramp}'s handling of the @code{ControlMaster} options, +and use your own settings in @file{~/.ssh/config}. @node Cleanup remote connections diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el index 88f5c2928e3..49ecaa58ee8 100644 --- a/lisp/net/tramp-adb.el +++ b/lisp/net/tramp-adb.el @@ -890,8 +890,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." "Like `make-process' for Tramp files. If connection property \"direct-async-process\" is non-nil, an alternative implementation will be used." - (if (tramp-get-connection-property - (tramp-dissect-file-name default-directory) "direct-async-process" nil) + (if (tramp-direct-async-process-p args) (apply #'tramp-handle-make-process args) (when args (with-parsed-tramp-file-name (expand-file-name default-directory) nil diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index 3e2eb023a33..ca43475f453 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -2790,8 +2790,7 @@ the result will be a local, non-Tramp, file name." STDERR can also be a file name. If connection property \"direct-async-process\" is non-nil, an alternative implementation will be used." - (if (tramp-get-connection-property - (tramp-dissect-file-name default-directory) "direct-async-process" nil) + (if (tramp-direct-async-process-p args) (apply #'tramp-handle-make-process args) (when args (with-parsed-tramp-file-name (expand-file-name default-directory) nil diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index d8113a9af9b..ab52bec39eb 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -3633,18 +3633,29 @@ User is always nil." (load local-copy noerror t nosuffix must-suffix) (delete-file local-copy))))) t))) + +(defun tramp-direct-async-process-p (&rest args) + "Whether direct async `make-process' can be called." + (let ((v (tramp-dissect-file-name default-directory))) + (and (tramp-get-connection-property v"direct-async-process" nil) + (not (tramp-multi-hop-p v)) + (not (plist-get args :stderr))))) + ;; We use BUFFER also as connection buffer during setup. Because of ;; this, its original contents must be saved, and restored once ;; connection has been setup. (defun tramp-handle-make-process (&rest args) - "An alternative `make-process' implementation for Tramp files." + "An alternative `make-process' implementation for Tramp files. +It does not support `:stderr'." (when args (with-parsed-tramp-file-name (expand-file-name default-directory) nil (let ((name (plist-get args :name)) (buffer (plist-get args :buffer)) (command (plist-get args :command)) + ;; FIXME: `:coding' shall be used. (coding (plist-get args :coding)) (noquery (plist-get args :noquery)) + ;; FIXME: `:connection-type' shall be used. (connection-type (plist-get args :connection-type)) (filter (plist-get args :filter)) (sentinel (plist-get args :sentinel)) @@ -3667,11 +3678,12 @@ User is always nil." (signal 'wrong-type-argument (list #'functionp filter))) (unless (or (null sentinel) (functionp sentinel)) (signal 'wrong-type-argument (list #'functionp sentinel))) - (unless (or (null stderr) (bufferp stderr) (stringp stderr)) - (signal 'wrong-type-argument (list #'stringp stderr))) - (when (and (stringp stderr) (tramp-tramp-file-p stderr) - (not (tramp-equal-remote default-directory stderr))) - (signal 'file-error (list "Wrong stderr" stderr))) + (when stderr + (signal + 'user-error + (list + "Stderr not supported for direct remote asynchronous processes" + stderr))) (let* ((buffer (if buffer @@ -3698,9 +3710,12 @@ User is always nil." (tramp-set-connection-property v "process-name" name) (tramp-set-connection-property v "process-buffer" buffer) + ;; Check for `tramp-sh-file-name-handler', because something + ;; is different between tramp-adb.el and tramp-sh.el. (with-current-buffer (tramp-get-connection-buffer v) (unwind-protect - (let* ((login-program + (let* ((sh-file-name-handler-p (tramp-sh-file-name-handler-p v)) + (login-program (tramp-get-method-parameter v 'tramp-login-program)) (login-args (tramp-get-method-parameter v 'tramp-login-args)) @@ -3716,12 +3731,12 @@ User is always nil." ;; in the main connection process, therefore ;; we cannot use `tramp-get-connection-process'. (tmpfile - (when (tramp-sh-file-name-handler-p v) + (when sh-file-name-handler-p (with-tramp-connection-property (tramp-get-process v) "temp-file" (tramp-compat-make-temp-name)))) (options - (when (tramp-sh-file-name-handler-p v) + (when sh-file-name-handler-p (tramp-compat-funcall 'tramp-ssh-controlmaster-options v))) spec) -- 2.39.5