diff options
| author | Michael Albinus | 2020-12-14 19:30:01 +0100 |
|---|---|---|
| committer | Michael Albinus | 2020-12-14 19:30:01 +0100 |
| commit | c0c6cd2d5d7af82ddfd4d8d080d0aa8d7882d293 (patch) | |
| tree | 176900038c02b3fcc984969464e51ce4aeb3f138 | |
| parent | 47a854bf24c8a36bf1e8ac32c8b5c9ebcba1d90a (diff) | |
| download | emacs-c0c6cd2d5d7af82ddfd4d8d080d0aa8d7882d293.tar.gz emacs-c0c6cd2d5d7af82ddfd4d8d080d0aa8d7882d293.zip | |
Add 'remote-file-error' for Tramp
* doc/lispref/errors.texi (Standard Errors): Add 'remote-file-error'.
* etc/NEWS: Mention 'remote-file-error'.
* lisp/net/ange-ftp.el (ftp-error): Add error condition
`remote-file-error'.
* lisp/net/tramp-cmds.el (tramp-cleanup-all-connections): Do not set
`tramp-locked'.
* lisp/net/tramp-compat.el (remote-file-error): Define if it
doesn't exist.
* lisp/net/tramp-sh.el (tramp-timeout-session): Check for "locked"
property.
(tramp-maybe-open-connection): Simplify.
* lisp/net/tramp.el (tramp-locked, tramp-locker): Remove them.
(tramp-file-name-handler): Do not set them.
(with-tramp-locked-connection): New defmacro.
(tramp-accept-process-output, tramp-send-string): Use it.
* src/fileio.c (Qremote_file_error): New error symbol.
* test/lisp/net/tramp-tests.el (tramp-test43-asynchronous-requests):
Adapt test. Remove :unstable tag.
| -rw-r--r-- | doc/lispref/errors.texi | 11 | ||||
| -rw-r--r-- | etc/NEWS | 61 | ||||
| -rw-r--r-- | lisp/net/ange-ftp.el | 2 | ||||
| -rw-r--r-- | lisp/net/tramp-cmds.el | 3 | ||||
| -rw-r--r-- | lisp/net/tramp-compat.el | 5 | ||||
| -rw-r--r-- | lisp/net/tramp-sh.el | 13 | ||||
| -rw-r--r-- | lisp/net/tramp.el | 113 | ||||
| -rw-r--r-- | src/fileio.c | 6 | ||||
| -rw-r--r-- | test/lisp/net/tramp-tests.el | 27 |
9 files changed, 132 insertions, 109 deletions
diff --git a/doc/lispref/errors.texi b/doc/lispref/errors.texi index cd8694be8a3..ff9b3e57125 100644 --- a/doc/lispref/errors.texi +++ b/doc/lispref/errors.texi | |||
| @@ -129,9 +129,18 @@ This is a subcategory of @code{file-error}. @xref{Modification Time}. | |||
| 129 | This is a subcategory of @code{file-error}. It happens, when a file | 129 | This is a subcategory of @code{file-error}. It happens, when a file |
| 130 | could not be watched for changes. @xref{File Notifications}. | 130 | could not be watched for changes. @xref{File Notifications}. |
| 131 | 131 | ||
| 132 | @item remote-file-error | ||
| 133 | This is a subcategory of @code{file-error}, which results from | ||
| 134 | problems in accessing a remote file. @xref{Remote Files,,, emacs, The | ||
| 135 | GNU Emacs Manual}. Often, this error appears when timers, process | ||
| 136 | filters, process sentinels or special events in general try to access | ||
| 137 | a remote file, and collide with another remote file operation. In | ||
| 138 | general it is a good idea to write a bug report. @xref{Reporting | ||
| 139 | Bugs,,, emacs, The GNU Emacs Manual}. | ||
| 140 | |||
| 132 | @c net/ange-ftp.el | 141 | @c net/ange-ftp.el |
| 133 | @item ftp-error | 142 | @item ftp-error |
| 134 | This is a subcategory of @code{file-error}, which results from | 143 | This is a subcategory of @code{remote-file-error}, which results from |
| 135 | problems in accessing a remote file using ftp. @xref{Remote Files,,, | 144 | problems in accessing a remote file using ftp. @xref{Remote Files,,, |
| 136 | emacs, The GNU Emacs Manual}. | 145 | emacs, The GNU Emacs Manual}. |
| 137 | 146 | ||
| @@ -89,7 +89,7 @@ useful on systems such as FreeBSD which ships only with "etc/termcap". | |||
| 89 | This is controlled by the new variable 'scroll-minibuffer-conservatively'. | 89 | This is controlled by the new variable 'scroll-minibuffer-conservatively'. |
| 90 | 90 | ||
| 91 | In addition, there is a new variable | 91 | In addition, there is a new variable |
| 92 | `redisplay-adhoc-scroll-in-resize-mini-windows` to disable the | 92 | 'redisplay-adhoc-scroll-in-resize-mini-windows' to disable the |
| 93 | ad-hoc auto-scrolling when resizing minibuffer windows. It has been | 93 | ad-hoc auto-scrolling when resizing minibuffer windows. It has been |
| 94 | found that its heuristic can be counter productive in some corner | 94 | found that its heuristic can be counter productive in some corner |
| 95 | cases, tho the cure may be worse than the disease. This said, the | 95 | cases, tho the cure may be worse than the disease. This said, the |
| @@ -303,8 +303,8 @@ the buffer cycles the whole buffer between "only top-level headings", | |||
| 303 | 303 | ||
| 304 | * Changes in Specialized Modes and Packages in Emacs 28.1 | 304 | * Changes in Specialized Modes and Packages in Emacs 28.1 |
| 305 | 305 | ||
| 306 | ** Loading dunnet.el in batch mode doesn't start the game any more | 306 | ** Loading dunnet.el in batch mode doesn't start the game any more. |
| 307 | Instead you need to do 'emacs -f dun-batch' to start the game in | 307 | Instead you need to do "emacs -f dun-batch" to start the game in |
| 308 | batch mode. | 308 | batch mode. |
| 309 | 309 | ||
| 310 | ** Emacs Server | 310 | ** Emacs Server |
| @@ -523,21 +523,20 @@ tags to be considered as well. | |||
| 523 | 523 | ||
| 524 | +++ | 524 | +++ |
| 525 | *** New user option 'gnus-registry-register-all'. | 525 | *** New user option 'gnus-registry-register-all'. |
| 526 | |||
| 527 | If non-nil (the default), create registry entries for all messages. | 526 | If non-nil (the default), create registry entries for all messages. |
| 528 | If nil, don't automatically create entries, they must be created | 527 | If nil, don't automatically create entries, they must be created |
| 529 | manually. | 528 | manually. |
| 530 | 529 | ||
| 531 | +++ | 530 | +++ |
| 532 | *** New user options to customise the summary line specs %[ and %]. | 531 | *** New user options to customise the summary line specs "%[" and "%]". |
| 533 | Four new options introduced in customisation group | 532 | Four new options introduced in customisation group |
| 534 | 'gnus-summary-format'. These are 'gnus-sum-opening-bracket', | 533 | 'gnus-summary-format'. These are 'gnus-sum-opening-bracket', |
| 535 | 'gnus-sum-closing-bracket', 'gnus-sum-opening-bracket-adopted', and | 534 | 'gnus-sum-closing-bracket', 'gnus-sum-opening-bracket-adopted', and |
| 536 | 'gnus-sum-closing-bracket-adopted'. Their default values are '[', ']', | 535 | 'gnus-sum-closing-bracket-adopted'. Their default values are "[", "]", |
| 537 | '<', '>' respectively. These variables control the appearance of '%[' | 536 | "<", ">" respectively. These options control the appearance of "%[" |
| 538 | and '%]' specs in the summary line format. '%[' will normally display | 537 | and "%]" specs in the summary line format. "%[" will normally display |
| 539 | the value of 'gnus-sum-opening-bracket', but can also be | 538 | the value of 'gnus-sum-opening-bracket', but can also be |
| 540 | 'gnus-sum-opening-bracket-adopted' for the adopted articles. '%]' will | 539 | 'gnus-sum-opening-bracket-adopted' for the adopted articles. "%]" will |
| 541 | normally display the value of 'gnus-sum-closing-bracket', but can also | 540 | normally display the value of 'gnus-sum-closing-bracket', but can also |
| 542 | be 'gnus-sum-closing-bracket-adopted' for the adopted articles. | 541 | be 'gnus-sum-closing-bracket-adopted' for the adopted articles. |
| 543 | 542 | ||
| @@ -1130,13 +1129,13 @@ If 'shr-width' is non-nil, it overrides this variable. | |||
| 1130 | ** Images | 1129 | ** Images |
| 1131 | 1130 | ||
| 1132 | --- | 1131 | --- |
| 1133 | ** Can explicitly specify base_uri for svg images. | 1132 | *** You can explicitly specify base_uri for svg images. |
| 1134 | ':base-uri' image property can be used to explicitly specify base_uri | 1133 | ':base-uri' image property can be used to explicitly specify base_uri |
| 1135 | for embedded images into svg. ':base-uri' is supported for both file | 1134 | for embedded images into svg. ':base-uri' is supported for both file |
| 1136 | and data svg images. | 1135 | and data svg images. |
| 1137 | 1136 | ||
| 1138 | +++ | 1137 | +++ |
| 1139 | ** 'svg-embed-base-uri-image' added to embed images | 1138 | *** 'svg-embed-base-uri-image' added to embed images. |
| 1140 | 'svg-embed-base-uri-image' can be used to embed images located | 1139 | 'svg-embed-base-uri-image' can be used to embed images located |
| 1141 | relatively to 'file-name-directory' of the ':base-uri' svg image property. | 1140 | relatively to 'file-name-directory' of the ':base-uri' svg image property. |
| 1142 | This works much faster then 'svg-embed'. | 1141 | This works much faster then 'svg-embed'. |
| @@ -1256,8 +1255,8 @@ project's root directory, respectively. | |||
| 1256 | So typing 'C-u RET' in the "*xref*" buffer quits its window | 1255 | So typing 'C-u RET' in the "*xref*" buffer quits its window |
| 1257 | before navigating to the selected location. | 1256 | before navigating to the selected location. |
| 1258 | 1257 | ||
| 1259 | *** New options xref-search-program and xref-search-program-alist. | 1258 | *** New user options 'xref-search-program' and 'xref-search-program-alist'. |
| 1260 | So far Grep and ripgrep are supported. ripgrep seems to offer better | 1259 | So far 'grep' and 'ripgrep' are supported. 'ripgrep' seems to offer better |
| 1261 | performance in certain cases, in particular for case-insensitive | 1260 | performance in certain cases, in particular for case-insensitive |
| 1262 | searches. | 1261 | searches. |
| 1263 | 1262 | ||
| @@ -1442,9 +1441,8 @@ that makes it a valid button. | |||
| 1442 | ** Miscellaneous | 1441 | ** Miscellaneous |
| 1443 | 1442 | ||
| 1444 | +++ | 1443 | +++ |
| 1445 | |||
| 1446 | *** New variable 'current-minibuffer-command'. | 1444 | *** New variable 'current-minibuffer-command'. |
| 1447 | This is like 'this-command', but is bound recursively when entering | 1445 | This is like 'this-command', but it is bound recursively when entering |
| 1448 | the minibuffer. | 1446 | the minibuffer. |
| 1449 | 1447 | ||
| 1450 | +++ | 1448 | +++ |
| @@ -1763,14 +1761,12 @@ used instead. | |||
| 1763 | * New Modes and Packages in Emacs 28.1 | 1761 | * New Modes and Packages in Emacs 28.1 |
| 1764 | 1762 | ||
| 1765 | ** Lisp Data mode | 1763 | ** Lisp Data mode |
| 1766 | |||
| 1767 | The new command 'lisp-data-mode' enables a major mode for buffers | 1764 | The new command 'lisp-data-mode' enables a major mode for buffers |
| 1768 | composed of Lisp symbolic expressions that do not form a computer | 1765 | composed of Lisp symbolic expressions that do not form a computer |
| 1769 | program. The ".dir-locals.el" file is automatically set to use this | 1766 | program. The ".dir-locals.el" file is automatically set to use this |
| 1770 | mode, as are other data files produced by Emacs. | 1767 | mode, as are other data files produced by Emacs. |
| 1771 | 1768 | ||
| 1772 | ** hierarchy.el | 1769 | ** hierarchy.el |
| 1773 | |||
| 1774 | It's a library to create, query, navigate and display hierarchy structures. | 1770 | It's a library to create, query, navigate and display hierarchy structures. |
| 1775 | 1771 | ||
| 1776 | ** New themes 'modus-vivendi' and 'modus-operandi'. | 1772 | ** New themes 'modus-vivendi' and 'modus-operandi'. |
| @@ -1781,13 +1777,12 @@ Consult the Modus Themes Info manual for more information on the user | |||
| 1781 | options they provide. | 1777 | options they provide. |
| 1782 | 1778 | ||
| 1783 | ** Dictionary mode | 1779 | ** Dictionary mode |
| 1784 | 1780 | This is a mode for searching a RFC 2229 dictionary server. | |
| 1785 | This is a mode for searching a RFC 2229 dictionary | 1781 | 'dictionary' opens a buffer for starting operations. |
| 1786 | server. 'dictionary' opens a buffer for starting | 1782 | 'dictionary-search' performs a lookup for a word. It also supports a |
| 1787 | operations. 'dictionary-search' performs a lookup for a word. It also | 1783 | 'dictionary-tooltip-mode' which performs a lookup of the word under |
| 1788 | supports a 'dictionary-tooltip-mode' which performs a lookup of the | 1784 | the mouse in 'dictionary-tooltip-dictionary' (which must be customized |
| 1789 | word under the mouse in 'dictionary-tooltip-dictionary' (which must be | 1785 | first). |
| 1790 | customized first). | ||
| 1791 | 1786 | ||
| 1792 | 1787 | ||
| 1793 | * Incompatible Editing Changes in Emacs 28.1 | 1788 | * Incompatible Editing Changes in Emacs 28.1 |
| @@ -1939,7 +1934,7 @@ ledit.el, lmenu.el, lucid.el and old-whitespace.el. | |||
| 1939 | 1934 | ||
| 1940 | * Lisp Changes in Emacs 28.1 | 1935 | * Lisp Changes in Emacs 28.1 |
| 1941 | 1936 | ||
| 1942 | ** New function `garbage-collect-maybe` to trigger GC early | 1937 | ** New function 'garbage-collect-maybe' to trigger GC early. |
| 1943 | 1938 | ||
| 1944 | --- | 1939 | --- |
| 1945 | ** 'defvar' detects the error of defining a variable currently lexically bound. | 1940 | ** 'defvar' detects the error of defining a variable currently lexically bound. |
| @@ -2164,6 +2159,20 @@ and 'play-sound-file'. | |||
| 2164 | If this variable is non-nil, character syntax is used for printing | 2159 | If this variable is non-nil, character syntax is used for printing |
| 2165 | numbers when this makes sense, such as '?A' for 65. | 2160 | numbers when this makes sense, such as '?A' for 65. |
| 2166 | 2161 | ||
| 2162 | ** New error 'remote-file-error', a subcategory of 'file-error'. | ||
| 2163 | It is signaled if a remote file operation fails due to internal | ||
| 2164 | reasons, and could block Emacs. It does not replace 'file-error' | ||
| 2165 | signals for the usual cases. Timers, process filters and process | ||
| 2166 | functions, which run remote file operations, shall protect themselves | ||
| 2167 | against this error. | ||
| 2168 | |||
| 2169 | If such an error occurs, please report this as bug via 'M-x report-emacs-bug'. | ||
| 2170 | Until it is solved you could ignore such errors by performing | ||
| 2171 | |||
| 2172 | (setq debug-ignored-errors (cons 'remote-file-error debug-ignored-errors)) | ||
| 2173 | |||
| 2174 | ** The error 'ftp-error' belongs also to category 'remote-file-error'. | ||
| 2175 | |||
| 2167 | 2176 | ||
| 2168 | * Changes in Emacs 28.1 on Non-Free Operating Systems | 2177 | * Changes in Emacs 28.1 on Non-Free Operating Systems |
| 2169 | 2178 | ||
diff --git a/lisp/net/ange-ftp.el b/lisp/net/ange-ftp.el index c627e1a088d..1922adb5480 100644 --- a/lisp/net/ange-ftp.el +++ b/lisp/net/ange-ftp.el | |||
| @@ -1080,7 +1080,7 @@ All HOST values should be in lower case.") | |||
| 1080 | (defvar ange-ftp-trample-marker) | 1080 | (defvar ange-ftp-trample-marker) |
| 1081 | 1081 | ||
| 1082 | ;; New error symbols. | 1082 | ;; New error symbols. |
| 1083 | (define-error 'ftp-error nil 'file-error) ;"FTP error" | 1083 | (define-error 'ftp-error nil '(remote-file-error file-error)) ;"FTP error" |
| 1084 | 1084 | ||
| 1085 | ;;; ------------------------------------------------------------ | 1085 | ;;; ------------------------------------------------------------ |
| 1086 | ;;; Enhanced message support. | 1086 | ;;; Enhanced message support. |
diff --git a/lisp/net/tramp-cmds.el b/lisp/net/tramp-cmds.el index 622116d9f90..9b6250430a8 100644 --- a/lisp/net/tramp-cmds.el +++ b/lisp/net/tramp-cmds.el | |||
| @@ -159,9 +159,6 @@ When called interactively, a Tramp connection has to be selected." | |||
| 159 | This includes password cache, file cache, connection cache, buffers." | 159 | This includes password cache, file cache, connection cache, buffers." |
| 160 | (interactive) | 160 | (interactive) |
| 161 | 161 | ||
| 162 | ;; Unlock Tramp. | ||
| 163 | (setq tramp-locked nil) | ||
| 164 | |||
| 165 | ;; Flush password cache. | 162 | ;; Flush password cache. |
| 166 | (password-reset) | 163 | (password-reset) |
| 167 | 164 | ||
diff --git a/lisp/net/tramp-compat.el b/lisp/net/tramp-compat.el index b44eabcfa8b..4c8d37d602c 100644 --- a/lisp/net/tramp-compat.el +++ b/lisp/net/tramp-compat.el | |||
| @@ -348,6 +348,11 @@ A nil value for either argument stands for the current time." | |||
| 348 | (lambda (fromstring tostring instring) | 348 | (lambda (fromstring tostring instring) |
| 349 | (replace-regexp-in-string (regexp-quote fromstring) tostring instring)))) | 349 | (replace-regexp-in-string (regexp-quote fromstring) tostring instring)))) |
| 350 | 350 | ||
| 351 | ;; Error symbol `remote-file-error' is defined in Emacs 28.1. We use | ||
| 352 | ;; an adapted error message in order to see that compatible symbol. | ||
| 353 | (unless (get 'remote-file-error 'error-conditions) | ||
| 354 | (define-error 'remote-file-error "Remote file error (compat)" 'file-error)) | ||
| 355 | |||
| 351 | (add-hook 'tramp-unload-hook | 356 | (add-hook 'tramp-unload-hook |
| 352 | (lambda () | 357 | (lambda () |
| 353 | (unload-feature 'tramp-loaddefs 'force) | 358 | (unload-feature 'tramp-loaddefs 'force) |
diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index 34be4fcba93..e9814cdadb9 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el | |||
| @@ -2944,7 +2944,8 @@ implementation will be used." | |||
| 2944 | (mapconcat | 2944 | (mapconcat |
| 2945 | #'tramp-shell-quote-argument uenv " ")) | 2945 | #'tramp-shell-quote-argument uenv " ")) |
| 2946 | "") | 2946 | "") |
| 2947 | (if heredoc (format "<<'%s'" tramp-end-of-heredoc) "") | 2947 | (if heredoc |
| 2948 | (format "<<'%s'" tramp-end-of-heredoc) "") | ||
| 2948 | (if tmpstderr (format "2>'%s'" tmpstderr) "") | 2949 | (if tmpstderr (format "2>'%s'" tmpstderr) "") |
| 2949 | (mapconcat #'tramp-shell-quote-argument env " ") | 2950 | (mapconcat #'tramp-shell-quote-argument env " ") |
| 2950 | (if heredoc | 2951 | (if heredoc |
| @@ -4914,7 +4915,8 @@ Goes through the list `tramp-inline-compress-commands'." | |||
| 4914 | (defun tramp-timeout-session (vec) | 4915 | (defun tramp-timeout-session (vec) |
| 4915 | "Close the connection VEC after a session timeout. | 4916 | "Close the connection VEC after a session timeout. |
| 4916 | If there is just some editing, retry it after 5 seconds." | 4917 | If there is just some editing, retry it after 5 seconds." |
| 4917 | (if (and tramp-locked tramp-locker | 4918 | (if (and (tramp-get-connection-property |
| 4919 | (tramp-get-connection-process vec) "locked" nil) | ||
| 4918 | (tramp-file-name-equal-p vec (car tramp-current-connection))) | 4920 | (tramp-file-name-equal-p vec (car tramp-current-connection))) |
| 4919 | (progn | 4921 | (progn |
| 4920 | (tramp-message | 4922 | (tramp-message |
| @@ -4958,10 +4960,9 @@ connection if a previous connection has died for some reason." | |||
| 4958 | (when (and (time-less-p | 4960 | (when (and (time-less-p |
| 4959 | 60 (time-since | 4961 | 60 (time-since |
| 4960 | (tramp-get-connection-property p "last-cmd-time" 0))) | 4962 | (tramp-get-connection-property p "last-cmd-time" 0))) |
| 4961 | (process-live-p p)) | 4963 | (process-live-p p) |
| 4962 | (tramp-send-command vec "echo are you awake" t t) | 4964 | (tramp-get-connection-property p "connected" nil)) |
| 4963 | (unless (and (process-live-p p) | 4965 | (unless (tramp-send-command-and-check vec "echo are you awake") |
| 4964 | (tramp-wait-for-output p 10)) | ||
| 4965 | ;; The error will be caught locally. | 4966 | ;; The error will be caught locally. |
| 4966 | (tramp-error vec 'file-error "Awake did fail"))) | 4967 | (tramp-error vec 'file-error "Awake did fail"))) |
| 4967 | (file-error | 4968 | (file-error |
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 6750a7ff4c6..70bf1eee26b 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el | |||
| @@ -2349,33 +2349,6 @@ Must be handled by the callers." | |||
| 2349 | res (cdr elt)))) | 2349 | res (cdr elt)))) |
| 2350 | res))) | 2350 | res))) |
| 2351 | 2351 | ||
| 2352 | ;; In Emacs, there is some concurrency due to timers. If a timer | ||
| 2353 | ;; interrupts Tramp and wishes to use the same connection buffer as | ||
| 2354 | ;; the "main" Emacs, then garbage might occur in the connection | ||
| 2355 | ;; buffer. Therefore, we need to make sure that a timer does not use | ||
| 2356 | ;; the same connection buffer as the "main" Emacs. We implement a | ||
| 2357 | ;; cheap global lock, instead of locking each connection buffer | ||
| 2358 | ;; separately. The global lock is based on two variables, | ||
| 2359 | ;; `tramp-locked' and `tramp-locker'. `tramp-locked' is set to true | ||
| 2360 | ;; (with setq) to indicate a lock. But Tramp also calls itself during | ||
| 2361 | ;; processing of a single file operation, so we need to allow | ||
| 2362 | ;; recursive calls. That's where the `tramp-locker' variable comes in | ||
| 2363 | ;; -- it is let-bound to t during the execution of the current | ||
| 2364 | ;; handler. So if `tramp-locked' is t and `tramp-locker' is also t, | ||
| 2365 | ;; then we should just proceed because we have been called | ||
| 2366 | ;; recursively. But if `tramp-locker' is nil, then we are a timer | ||
| 2367 | ;; interrupting the "main" Emacs, and then we signal an error. | ||
| 2368 | |||
| 2369 | (defvar tramp-locked nil | ||
| 2370 | "If non-nil, then Tramp is currently busy. | ||
| 2371 | Together with `tramp-locker', this implements a locking mechanism | ||
| 2372 | preventing reentrant calls of Tramp.") | ||
| 2373 | |||
| 2374 | (defvar tramp-locker nil | ||
| 2375 | "If non-nil, then a caller has locked Tramp. | ||
| 2376 | Together with `tramp-locked', this implements a locking mechanism | ||
| 2377 | preventing reentrant calls of Tramp.") | ||
| 2378 | |||
| 2379 | ;; Main function. | 2352 | ;; Main function. |
| 2380 | (defun tramp-file-name-handler (operation &rest args) | 2353 | (defun tramp-file-name-handler (operation &rest args) |
| 2381 | "Invoke Tramp file name handler for OPERATION and ARGS. | 2354 | "Invoke Tramp file name handler for OPERATION and ARGS. |
| @@ -2429,17 +2402,7 @@ Fall back to normal file name handler if no Tramp file name handler exists." | |||
| 2429 | (setq result | 2402 | (setq result |
| 2430 | (catch 'non-essential | 2403 | (catch 'non-essential |
| 2431 | (catch 'suppress | 2404 | (catch 'suppress |
| 2432 | (when (and tramp-locked (not tramp-locker)) | 2405 | (apply foreign operation args)))) |
| 2433 | (setq tramp-locked nil) | ||
| 2434 | (tramp-error | ||
| 2435 | v 'file-error | ||
| 2436 | "Forbidden reentrant call of Tramp")) | ||
| 2437 | (let ((tl tramp-locked)) | ||
| 2438 | (setq tramp-locked t) | ||
| 2439 | (unwind-protect | ||
| 2440 | (let ((tramp-locker t)) | ||
| 2441 | (apply foreign operation args)) | ||
| 2442 | (setq tramp-locked tl)))))) | ||
| 2443 | ;; (tramp-message | 2406 | ;; (tramp-message |
| 2444 | ;; v 4 "Running `%s'...`%s'" (cons operation args) result) | 2407 | ;; v 4 "Running `%s'...`%s'" (cons operation args) result) |
| 2445 | (cond | 2408 | (cond |
| @@ -4499,6 +4462,32 @@ performed successfully. Any other value means an error." | |||
| 4499 | 4462 | ||
| 4500 | ;;; Utility functions: | 4463 | ;;; Utility functions: |
| 4501 | 4464 | ||
| 4465 | ;; In Emacs, there is some concurrency due to timers. If a timer | ||
| 4466 | ;; interrupts Tramp and wishes to use the same connection buffer as | ||
| 4467 | ;; the "main" Emacs, then garbage might occur in the connection | ||
| 4468 | ;; buffer. Therefore, we need to make sure that a timer does not use | ||
| 4469 | ;; the same connection buffer as the "main" Emacs. We lock each | ||
| 4470 | ;; connection process separately by a connection property. | ||
| 4471 | |||
| 4472 | (defmacro with-tramp-locked-connection (proc &rest body) | ||
| 4473 | "Lock PROC for other communication, and run BODY. | ||
| 4474 | Mostly useful to protect BODY from being interrupted by timers." | ||
| 4475 | (declare (indent 1) (debug t)) | ||
| 4476 | `(if (tramp-get-connection-property ,proc "locked" nil) | ||
| 4477 | ;; Be kind for older Emacsen. | ||
| 4478 | (if (member 'remote-file-error debug-ignored-errors) | ||
| 4479 | (throw 'non-essential 'non-essential) | ||
| 4480 | (tramp-error | ||
| 4481 | ,proc 'remote-file-error "Forbidden reentrant call of Tramp")) | ||
| 4482 | (unwind-protect | ||
| 4483 | (progn | ||
| 4484 | (tramp-set-connection-property ,proc "locked" t) | ||
| 4485 | ,@body) | ||
| 4486 | (tramp-flush-connection-property ,proc "locked")))) | ||
| 4487 | |||
| 4488 | (font-lock-add-keywords | ||
| 4489 | 'emacs-lisp-mode '("\\<with-tramp-locked-connection\\>")) | ||
| 4490 | |||
| 4502 | (defun tramp-accept-process-output (proc &optional timeout) | 4491 | (defun tramp-accept-process-output (proc &optional timeout) |
| 4503 | "Like `accept-process-output' for Tramp processes. | 4492 | "Like `accept-process-output' for Tramp processes. |
| 4504 | This is needed in order to hide `last-coding-system-used', which is set | 4493 | This is needed in order to hide `last-coding-system-used', which is set |
| @@ -4508,15 +4497,17 @@ If the user quits via `C-g', it is propagated up to `tramp-file-name-handler'." | |||
| 4508 | (let ((inhibit-read-only t) | 4497 | (let ((inhibit-read-only t) |
| 4509 | last-coding-system-used | 4498 | last-coding-system-used |
| 4510 | result) | 4499 | result) |
| 4511 | ;; JUST-THIS-ONE is set due to Bug#12145. `with-local-quit' | 4500 | ;; This must be protected by the "locked" property. |
| 4512 | ;; returns t in order to report success. | 4501 | (with-tramp-locked-connection proc |
| 4513 | (if (with-local-quit | 4502 | ;; JUST-THIS-ONE is set due to Bug#12145. `with-local-quit' |
| 4514 | (setq result (accept-process-output proc timeout nil t)) t) | 4503 | ;; returns t in order to report success. |
| 4515 | (tramp-message | 4504 | (if (with-local-quit |
| 4516 | proc 10 "%s %s %s %s\n%s" | 4505 | (setq result (accept-process-output proc timeout nil t)) t) |
| 4517 | proc timeout (process-status proc) result (buffer-string)) | 4506 | (tramp-message |
| 4518 | ;; Propagate quit. | 4507 | proc 10 "%s %s %s %s\n%s" |
| 4519 | (keyboard-quit)) | 4508 | proc timeout (process-status proc) result (buffer-string)) |
| 4509 | ;; Propagate quit. | ||
| 4510 | (keyboard-quit))) | ||
| 4520 | result))) | 4511 | result))) |
| 4521 | 4512 | ||
| 4522 | (defun tramp-search-regexp (regexp) | 4513 | (defun tramp-search-regexp (regexp) |
| @@ -4633,19 +4624,21 @@ the remote host use line-endings as defined in the variable | |||
| 4633 | (unless (or (string-empty-p string) | 4624 | (unless (or (string-empty-p string) |
| 4634 | (string-equal (substring string -1) tramp-rsh-end-of-line)) | 4625 | (string-equal (substring string -1) tramp-rsh-end-of-line)) |
| 4635 | (setq string (concat string tramp-rsh-end-of-line))) | 4626 | (setq string (concat string tramp-rsh-end-of-line))) |
| 4636 | ;; Send the string. | 4627 | ;; This must be protected by the "locked" property. |
| 4637 | (with-local-quit | 4628 | (with-tramp-locked-connection p |
| 4638 | (if (and chunksize (not (zerop chunksize))) | 4629 | ;; Send the string. |
| 4639 | (let ((pos 0) | 4630 | (with-local-quit |
| 4640 | (end (length string))) | 4631 | (if (and chunksize (not (zerop chunksize))) |
| 4641 | (while (< pos end) | 4632 | (let ((pos 0) |
| 4642 | (tramp-message | 4633 | (end (length string))) |
| 4643 | vec 10 "Sending chunk from %s to %s" | 4634 | (while (< pos end) |
| 4644 | pos (min (+ pos chunksize) end)) | 4635 | (tramp-message |
| 4645 | (process-send-string | 4636 | vec 10 "Sending chunk from %s to %s" |
| 4646 | p (substring string pos (min (+ pos chunksize) end))) | 4637 | pos (min (+ pos chunksize) end)) |
| 4647 | (setq pos (+ pos chunksize)))) | 4638 | (process-send-string |
| 4648 | (process-send-string p string)))))) | 4639 | p (substring string pos (min (+ pos chunksize) end))) |
| 4640 | (setq pos (+ pos chunksize)))) | ||
| 4641 | (process-send-string p string))))))) | ||
| 4649 | 4642 | ||
| 4650 | (defun tramp-process-sentinel (proc event) | 4643 | (defun tramp-process-sentinel (proc event) |
| 4651 | "Flush file caches and remove shell prompt." | 4644 | "Flush file caches and remove shell prompt." |
diff --git a/src/fileio.c b/src/fileio.c index 702c1438283..c97f4daf20c 100644 --- a/src/fileio.c +++ b/src/fileio.c | |||
| @@ -6259,6 +6259,7 @@ syms_of_fileio (void) | |||
| 6259 | DEFSYM (Qfile_date_error, "file-date-error"); | 6259 | DEFSYM (Qfile_date_error, "file-date-error"); |
| 6260 | DEFSYM (Qfile_missing, "file-missing"); | 6260 | DEFSYM (Qfile_missing, "file-missing"); |
| 6261 | DEFSYM (Qfile_notify_error, "file-notify-error"); | 6261 | DEFSYM (Qfile_notify_error, "file-notify-error"); |
| 6262 | DEFSYM (Qremote_file_error, "remote-file-error"); | ||
| 6262 | DEFSYM (Qexcl, "excl"); | 6263 | DEFSYM (Qexcl, "excl"); |
| 6263 | 6264 | ||
| 6264 | DEFVAR_LISP ("file-name-coding-system", Vfile_name_coding_system, | 6265 | DEFVAR_LISP ("file-name-coding-system", Vfile_name_coding_system, |
| @@ -6320,6 +6321,11 @@ behaves as if file names were encoded in `utf-8'. */); | |||
| 6320 | Fput (Qfile_notify_error, Qerror_message, | 6321 | Fput (Qfile_notify_error, Qerror_message, |
| 6321 | build_pure_c_string ("File notification error")); | 6322 | build_pure_c_string ("File notification error")); |
| 6322 | 6323 | ||
| 6324 | Fput (Qremote_file_error, Qerror_conditions, | ||
| 6325 | Fpurecopy (list3 (Qremote_file_error, Qfile_error, Qerror))); | ||
| 6326 | Fput (Qremote_file_error, Qerror_message, | ||
| 6327 | build_pure_c_string ("Remote file error")); | ||
| 6328 | |||
| 6323 | DEFVAR_LISP ("file-name-handler-alist", Vfile_name_handler_alist, | 6329 | DEFVAR_LISP ("file-name-handler-alist", Vfile_name_handler_alist, |
| 6324 | doc: /* Alist of elements (REGEXP . HANDLER) for file names handled specially. | 6330 | doc: /* Alist of elements (REGEXP . HANDLER) for file names handled specially. |
| 6325 | If a file name matches REGEXP, all I/O on that file is done by calling | 6331 | If a file name matches REGEXP, all I/O on that file is done by calling |
diff --git a/test/lisp/net/tramp-tests.el b/test/lisp/net/tramp-tests.el index 819a3dfecf5..0a5931d6893 100644 --- a/test/lisp/net/tramp-tests.el +++ b/test/lisp/net/tramp-tests.el | |||
| @@ -4817,6 +4817,7 @@ INPUT, if non-nil, is a string sent to the process." | |||
| 4817 | ;; this test cannot run properly. | 4817 | ;; this test cannot run properly. |
| 4818 | :tags '(:expensive-test :unstable) | 4818 | :tags '(:expensive-test :unstable) |
| 4819 | (skip-unless (tramp--test-enabled)) | 4819 | (skip-unless (tramp--test-enabled)) |
| 4820 | (skip-unless nil) | ||
| 4820 | (skip-unless (or (tramp--test-adb-p) (tramp--test-sh-p))) | 4821 | (skip-unless (or (tramp--test-adb-p) (tramp--test-sh-p))) |
| 4821 | (skip-unless (not (tramp--test-crypt-p))) | 4822 | (skip-unless (not (tramp--test-crypt-p))) |
| 4822 | ;; Prior Emacs 27, `shell-command-dont-erase-buffer' wasn't working properly. | 4823 | ;; Prior Emacs 27, `shell-command-dont-erase-buffer' wasn't working properly. |
| @@ -6236,15 +6237,14 @@ This is needed in timer functions as well as process filters and sentinels." | |||
| 6236 | "Check parallel asynchronous requests. | 6237 | "Check parallel asynchronous requests. |
| 6237 | Such requests could arrive from timers, process filters and | 6238 | Such requests could arrive from timers, process filters and |
| 6238 | process sentinels. They shall not disturb each other." | 6239 | process sentinels. They shall not disturb each other." |
| 6239 | ;; The test fails from time to time, w/o a reproducible pattern. So | 6240 | :tags '(:expensive-test) |
| 6240 | ;; we mark it as unstable. | ||
| 6241 | :tags '(:expensive-test :unstable) | ||
| 6242 | (skip-unless (tramp--test-enabled)) | 6241 | (skip-unless (tramp--test-enabled)) |
| 6243 | ;; Prior Emacs 27, `shell-file-name' was hard coded as "/bin/sh" for | 6242 | ;; Prior Emacs 27, `shell-file-name' was hard coded as "/bin/sh" for |
| 6244 | ;; remote processes in Emacs. That doesn't work for tramp-adb.el. | 6243 | ;; remote processes in Emacs. That doesn't work for tramp-adb.el. |
| 6245 | (skip-unless (or (and (tramp--test-adb-p) (tramp--test-emacs27-p)) | 6244 | (skip-unless (or (and (tramp--test-adb-p) (tramp--test-emacs27-p)) |
| 6246 | (tramp--test-sh-p))) | 6245 | (tramp--test-sh-p))) |
| 6247 | (skip-unless (not (tramp--test-crypt-p))) | 6246 | (skip-unless (not (tramp--test-crypt-p))) |
| 6247 | (skip-unless (not (tramp--test-docker-p))) | ||
| 6248 | 6248 | ||
| 6249 | (with-timeout | 6249 | (with-timeout |
| 6250 | (tramp--test-asynchronous-requests-timeout (tramp--test-timeout-handler)) | 6250 | (tramp--test-asynchronous-requests-timeout (tramp--test-timeout-handler)) |
| @@ -6283,10 +6283,10 @@ process sentinels. They shall not disturb each other." | |||
| 6283 | ((getenv "EMACS_HYDRA_CI") 10) | 6283 | ((getenv "EMACS_HYDRA_CI") 10) |
| 6284 | (t 1))) | 6284 | (t 1))) |
| 6285 | ;; We must distinguish due to performance reasons. | 6285 | ;; We must distinguish due to performance reasons. |
| 6286 | ;; (timer-operation | 6286 | (timer-operation |
| 6287 | ;; (cond | 6287 | (cond |
| 6288 | ;; ((tramp--test-mock-p) #'vc-registered) | 6288 | ((tramp--test-mock-p) #'vc-registered) |
| 6289 | ;; (t #'file-attributes))) | 6289 | (t #'file-attributes))) |
| 6290 | ;; This is when all timers start. We check inside the | 6290 | ;; This is when all timers start. We check inside the |
| 6291 | ;; timer function, that we don't exceed timeout. | 6291 | ;; timer function, that we don't exceed timeout. |
| 6292 | (timer-start (current-time)) | 6292 | (timer-start (current-time)) |
| @@ -6314,10 +6314,15 @@ process sentinels. They shall not disturb each other." | |||
| 6314 | (default-directory tmp-name) | 6314 | (default-directory tmp-name) |
| 6315 | (file | 6315 | (file |
| 6316 | (buffer-name | 6316 | (buffer-name |
| 6317 | (nth (random (length buffers)) buffers)))) | 6317 | (nth (random (length buffers)) buffers))) |
| 6318 | ;; A remote operation in a timer could | ||
| 6319 | ;; confuse Tramp heavily. So we ignore this | ||
| 6320 | ;; error here. | ||
| 6321 | (debug-ignored-errors | ||
| 6322 | (cons 'remote-file-error debug-ignored-errors))) | ||
| 6318 | (tramp--test-message | 6323 | (tramp--test-message |
| 6319 | "Start timer %s %s" file (current-time-string)) | 6324 | "Start timer %s %s" file (current-time-string)) |
| 6320 | ;; (funcall timer-operation file) | 6325 | (funcall timer-operation file) |
| 6321 | (tramp--test-message | 6326 | (tramp--test-message |
| 6322 | "Stop timer %s %s" file (current-time-string)) | 6327 | "Stop timer %s %s" file (current-time-string)) |
| 6323 | ;; Adjust timer if it takes too much time. | 6328 | ;; Adjust timer if it takes too much time. |
| @@ -6618,14 +6623,12 @@ If INTERACTIVE is non-nil, the tests are run interactively." | |||
| 6618 | 6623 | ||
| 6619 | ;; * Work on skipped tests. Make a comment, when it is impossible. | 6624 | ;; * Work on skipped tests. Make a comment, when it is impossible. |
| 6620 | ;; * Revisit expensive tests, once problems in `tramp-error' are solved. | 6625 | ;; * Revisit expensive tests, once problems in `tramp-error' are solved. |
| 6621 | ;; * Fix `tramp-test05-expand-file-name-relative' in `expand-file-name'. | ||
| 6622 | ;; * Fix `tramp-test06-directory-file-name' for `ftp'. | 6626 | ;; * Fix `tramp-test06-directory-file-name' for `ftp'. |
| 6623 | ;; * Investigate, why `tramp-test11-copy-file' and `tramp-test12-rename-file' | 6627 | ;; * Investigate, why `tramp-test11-copy-file' and `tramp-test12-rename-file' |
| 6624 | ;; do not work properly for `nextcloud'. | 6628 | ;; do not work properly for `nextcloud'. |
| 6625 | ;; * Implement `tramp-test31-interrupt-process' for `adb' and for | 6629 | ;; * Implement `tramp-test31-interrupt-process' for `adb' and for |
| 6626 | ;; direct async processes. | 6630 | ;; direct async processes. |
| 6627 | ;; * Fix Bug#16928 in `tramp-test43-asynchronous-requests'. A remote | 6631 | ;; * Fix `tramp-test44-threads'. |
| 6628 | ;; file name operation cannot run in the timer. Remove `:unstable' tag? | ||
| 6629 | 6632 | ||
| 6630 | (provide 'tramp-tests) | 6633 | (provide 'tramp-tests) |
| 6631 | 6634 | ||