@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}.
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
(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))
(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
(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))
;; 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)