From 1a5293e724fd1d0d959497931bfd4274df248c38 Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Sat, 13 Jan 2018 12:07:28 +0100 Subject: [PATCH] Improve Tramp robustness * lisp/net/tramp.el (tramp-message, tramp-process-actions) (tramp-read-passwd, tramp-interrupt-process): * lisp/net/tramp-adb.el (tramp-adb-maybe-open-connection): * lisp/net/tramp-gvfs.el (tramp-gvfs-handle-file-notify-add-watch) (tramp-gvfs-maybe-open-connection): * lisp/net/tramp-sh.el (tramp-do-copy-or-rename-file-out-of-band) (tramp-process-sentinel) (tramp-sh-handle-file-notify-add-watch) (tramp-barf-if-no-shell-prompt, tramp-maybe-open-connection) * lisp/net/tramp-smb.el (tramp-smb-handle-copy-directory) (tramp-smb-handle-file-acl, tramp-smb-handle-set-file-acl) (tramp-smb-maybe-open-connection): Use process property rather than connection property "vector". * lisp/net/tramp-gvfs.el (tramp-gvfs-handle-file-notify-add-watch): Fix scoping error. Let error traces use process buffer. * lisp/net/tramp-sh.el (tramp-sh-handle-file-notify-add-watch): Move "inotifywait" up. GVFS based monitoring is not stable. Let error traces use process buffer. (tramp-sh-gvfs-monitor-dir-process-filter): Check more error messages. (tramp-get-remote-gvfs-monitor-dir): Search also for "gio". * lisp/net/tramp.el (tramp-get-debug-buffer): Use `special-mode-map' as parent map in debug buffer. (tramp-message): Ensure, that proper process buffer is dumped in error case. --- lisp/net/tramp-adb.el | 2 +- lisp/net/tramp-gvfs.el | 10 ++++----- lisp/net/tramp-sh.el | 46 +++++++++++++++++++++++------------------- lisp/net/tramp-smb.el | 8 ++++---- lisp/net/tramp.el | 34 +++++++++++++++---------------- 5 files changed, 52 insertions(+), 48 deletions(-) diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el index aa71effdd92..f5c45f68e94 100644 --- a/lisp/net/tramp-adb.el +++ b/lisp/net/tramp-adb.el @@ -1283,7 +1283,7 @@ connection if a previous connection has died for some reason." (tramp-adb-wait-for-output p 30) (unless (process-live-p p) (tramp-error vec 'file-error "Terminated!")) - (tramp-set-connection-property p "vector" vec) + (process-put p 'vector vec) (process-put p 'adjust-window-size-function 'ignore) (set-process-query-on-exit-flag p nil) diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el index ffe3bd28bd2..6745ae02c7b 100644 --- a/lisp/net/tramp-gvfs.el +++ b/lisp/net/tramp-gvfs.el @@ -1304,14 +1304,14 @@ If FILE-SYSTEM is non-nil, return file system attributes." 'start-process "gvfs-monitor" (generate-new-buffer " *gvfs-monitor*") (if (tramp-gvfs-gio-tool-p v) - `("gio" "monitor" ,(tramp-gvfs-url-file-name file-name))) - `("gvfs-monitor-file" (tramp-gvfs-url-file-name file-name))))) + `("gio" "monitor" ,(tramp-gvfs-url-file-name file-name)) + `("gvfs-monitor-file" (tramp-gvfs-url-file-name file-name)))))) (if (not (processp p)) (tramp-error v 'file-notify-error "Monitoring not supported for `%s'" file-name) (tramp-message v 6 "Run `%s', %S" (mapconcat 'identity (process-command p) " ") p) - (tramp-set-connection-property p "vector" v) + (process-put p 'vector v) (process-put p 'events events) (process-put p 'watch-name localname) (process-put p 'adjust-window-size-function 'ignore) @@ -1322,7 +1322,7 @@ If FILE-SYSTEM is non-nil, return file system attributes." (tramp-accept-process-output p 1) (unless (process-live-p p) (tramp-error - v 'file-notify-error "Monitoring not supported for `%s'" file-name)) + p 'file-notify-error "Monitoring not supported for `%s'" file-name)) p)))) (defun tramp-gvfs-monitor-file-process-filter (proc string) @@ -1930,7 +1930,7 @@ connection if a previous connection has died for some reason." :name (tramp-buffer-name vec) :buffer (tramp-get-connection-buffer vec) :server t :host 'local :service t :noquery t))) - (tramp-set-connection-property p "vector" vec) + (process-put p 'vector vec) (set-process-query-on-exit-flag p nil))) (unless (tramp-gvfs-connection-mounted-p vec) diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index b7693f8edb5..09d83dd5300 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -2507,7 +2507,7 @@ The method used must be an out-of-band method." (tramp-get-connection-buffer v) command)))) (tramp-message orig-vec 6 "%s" command) - (tramp-set-connection-property p "vector" orig-vec) + (process-put p 'vector orig-vec) (process-put p 'adjust-window-size-function 'ignore) (set-process-query-on-exit-flag p nil) @@ -2822,7 +2822,7 @@ the result will be a local, non-Tramp, file name." (defun tramp-process-sentinel (proc event) "Flush file caches." (unless (process-live-p proc) - (let ((vec (tramp-get-connection-property proc "vector" nil))) + (let ((vec (process-get proc 'vector))) (when vec (tramp-message vec 5 "Sentinel called: `%S' `%s'" proc event) (tramp-flush-connection-properties proc) @@ -3563,19 +3563,7 @@ Fall back to normal file name handler if no Tramp handler exists." (let ((default-directory (file-name-directory file-name)) command events filter p sequence) (cond - ;; gvfs-monitor-dir. - ((setq command (tramp-get-remote-gvfs-monitor-dir v)) - (setq filter 'tramp-sh-gvfs-monitor-dir-process-filter - events - (cond - ((and (memq 'change flags) (memq 'attribute-change flags)) - '(created changed changes-done-hint moved deleted - attribute-changed)) - ((memq 'change flags) - '(created changed changes-done-hint moved deleted)) - ((memq 'attribute-change flags) '(attribute-changed))) - sequence `(,command ,localname))) - ;; inotifywait. + ;; "inotifywait". ((setq command (tramp-get-remote-inotifywait v)) (setq filter 'tramp-sh-inotifywait-process-filter events @@ -3593,6 +3581,20 @@ Fall back to normal file name handler if no Tramp handler exists." (mapcar (lambda (x) (intern-soft (replace-regexp-in-string "_" "-" x))) (split-string events "," 'omit)))) + ;; "gvfs-monitor-dir" or "gio monitor". + ((setq command (tramp-get-remote-gvfs-monitor-dir v)) + (setq filter 'tramp-sh-gvfs-monitor-dir-process-filter + events + (cond + ((and (memq 'change flags) (memq 'attribute-change flags)) + '(created changed changes-done-hint moved deleted + attribute-changed)) + ((memq 'change flags) + '(created changed changes-done-hint moved deleted)) + ((memq 'attribute-change flags) '(attribute-changed))) + sequence (if (string-match "/gio$" command) + `(,command "monitor" ,localname) + `(,command ,localname)))) ;; None. (t (tramp-error v 'file-notify-error @@ -3612,7 +3614,7 @@ Fall back to normal file name handler if no Tramp handler exists." "`%s' failed to start on remote host" (mapconcat 'identity sequence " ")) (tramp-message v 6 "Run `%s', %S" (mapconcat 'identity sequence " ") p) - (tramp-set-connection-property p "vector" v) + (process-put p 'vector v) ;; Needed for process filter. (process-put p 'events events) (process-put p 'watch-name localname) @@ -3623,7 +3625,7 @@ Fall back to normal file name handler if no Tramp handler exists." (tramp-accept-process-output p 1) (unless (process-live-p p) (tramp-error - v 'file-notify-error "Monitoring not supported for `%s'" file-name)) + p 'file-notify-error "Monitoring not supported for `%s'" file-name)) p)))) (defun tramp-sh-gvfs-monitor-dir-process-filter (proc string) @@ -3641,7 +3643,8 @@ file-notify events." ;; Attribute change is returned in unused wording. string (replace-regexp-in-string "ATTRIB CHANGED" "ATTRIBUTE_CHANGED" string)) - (when (string-match "Monitoring not supported" string) + ;; https://bugs.launchpad.net/bugs/1742946 + (when (string-match "Monitoring not supported\\|No locations given" string) (delete-process proc)) (while (string-match @@ -4027,7 +4030,7 @@ file exists and nonzero exit status otherwise." "Wait for shell prompt and barf if none appears. Looks at process PROC to see if a shell prompt appears in TIMEOUT seconds. If not, it produces an error message with the given ERROR-ARGS." - (let ((vec (tramp-get-connection-property proc "vector" nil))) + (let ((vec (process-get proc 'vector))) (condition-case nil (tramp-wait-for-regexp proc timeout @@ -4743,8 +4746,8 @@ connection if a previous connection has died for some reason." (list tramp-encoding-shell)))))) ;; Set sentinel and query flag. Initialize variables. - (tramp-set-connection-property p "vector" vec) (set-process-sentinel p 'tramp-process-sentinel) + (process-put p 'vector vec) (process-put p 'adjust-window-size-function 'ignore) (set-process-query-on-exit-flag p nil) (setq tramp-current-connection (cons vec (current-time))) @@ -5462,7 +5465,8 @@ This command is returned only if `delete-by-moving-to-trash' is non-nil." ;; We distinguish "gvfs-monitor-dir.exe" from cygwin in order to ;; establish better timeouts in filenotify-tests.el. Any better ;; distinction approach would be welcome! - (or (tramp-find-executable + (or (tramp-find-executable vec "gio" (tramp-get-remote-path vec) t t) + (tramp-find-executable vec "gvfs-monitor-dir.exe" (tramp-get-remote-path vec) t t) (tramp-find-executable vec "gvfs-monitor-dir" (tramp-get-remote-path vec) t t)))) diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el index c8697285360..e0a416ac371 100644 --- a/lisp/net/tramp-smb.el +++ b/lisp/net/tramp-smb.el @@ -519,7 +519,7 @@ pass to the OPERATION." (tramp-message v 6 "%s" (mapconcat 'identity (process-command p) " ")) - (tramp-set-connection-property p "vector" v) + (process-put p 'vector v) (process-put p 'adjust-window-size-function 'ignore) (set-process-query-on-exit-flag p nil) (tramp-process-actions p v nil tramp-smb-actions-with-tar) @@ -776,7 +776,7 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." (tramp-message v 6 "%s" (mapconcat 'identity (process-command p) " ")) - (tramp-set-connection-property p "vector" v) + (process-put p 'vector v) (process-put p 'adjust-window-size-function 'ignore) (set-process-query-on-exit-flag p nil) (tramp-process-actions p v nil tramp-smb-actions-get-acl) @@ -1433,7 +1433,7 @@ component is used as the target of the symlink." (tramp-message v 6 "%s" (mapconcat 'identity (process-command p) " ")) - (tramp-set-connection-property p "vector" v) + (process-put p 'vector v) (process-put p 'adjust-window-size-function 'ignore) (set-process-query-on-exit-flag p nil) (tramp-process-actions p v nil tramp-smb-actions-set-acl) @@ -1960,7 +1960,7 @@ If ARGUMENT is non-nil, use it as argument for (tramp-message vec 6 "%s" (mapconcat 'identity (process-command p) " ")) - (tramp-set-connection-property p "vector" vec) + (process-put p 'vector vec) (process-put p 'adjust-window-size-function 'ignore) (set-process-query-on-exit-flag p nil) diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 72321dbdeba..d1100f0206e 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -1558,7 +1558,9 @@ The outline level is equal to the verbosity of the Tramp message." (outline-regexp tramp-debug-outline-regexp)) (outline-mode)) (set (make-local-variable 'outline-regexp) tramp-debug-outline-regexp) - (set (make-local-variable 'outline-level) 'tramp-debug-outline-level)) + (set (make-local-variable 'outline-level) 'tramp-debug-outline-level) + ;; Do not edit the debug buffer. + (set-keymap-parent (current-local-map) special-mode-map)) (current-buffer))) (defsubst tramp-debug-message (vec fmt-string &rest arguments) @@ -1663,17 +1665,18 @@ applicable)." arguments)) ;; Log only when there is a minimum level. (when (>= tramp-verbose 4) - ;; Translate proc to vec. - (when (processp vec-or-proc) - (let ((tramp-verbose 0)) - (setq vec-or-proc - (tramp-get-connection-property vec-or-proc "vector" nil)))) - ;; Append connection buffer for error messages. - (when (= level 1) - (let ((tramp-verbose 0)) - (with-current-buffer (tramp-get-connection-buffer vec-or-proc) + (let ((tramp-verbose 0)) + ;; Append connection buffer for error messages. + (when (= level 1) + (with-current-buffer + (if (processp vec-or-proc) + (process-buffer vec-or-proc) + (tramp-get-connection-buffer vec-or-proc)) (setq fmt-string (concat fmt-string "\n%s") - arguments (append arguments (list (buffer-string))))))) + arguments (append arguments (list (buffer-string)))))) + ;; Translate proc to vec. + (when (processp vec-or-proc) + (setq vec-or-proc (process-get vec-or-proc 'vector)))) ;; Do it. (when (tramp-file-name-p vec-or-proc) (apply 'tramp-debug-message @@ -3787,8 +3790,7 @@ connection buffer." ;; use the "password-vector" property in case we have several hops. (tramp-set-connection-property (tramp-get-connection-property - proc "password-vector" - (tramp-get-connection-property proc "vector" nil)) + proc "password-vector" (process-get proc 'vector)) "first-password-request" tramp-cache-read-persistent-data) (save-restriction (with-tramp-progress-reporter @@ -4405,9 +4407,7 @@ Invokes `password-read' if available, `read-passwd' else." ;; In tramp-sh.el, we must use "password-vector" due to ;; multi-hop. (tramp-get-connection-property - proc "password-vector" - ;; All other backends simply use "vector". - (tramp-get-connection-property proc "vector" nil)) + proc "password-vector" (process-get proc 'vector)) 'noloc 'nohop)) (pw-prompt (or prompt @@ -4553,7 +4553,7 @@ Only works for Bourne-like shells." ;; This is for tramp-sh.el. Other backends do not support this (yet). (tramp-compat-funcall 'tramp-send-command - (tramp-get-connection-property proc "vector" nil) + (process-get proc 'vector) (format "kill -2 %d" pid)) ;; Wait, until the process has disappeared. If it doesn't, ;; fall back to the default implementation. -- 2.39.2