aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Albinus2020-12-14 19:30:01 +0100
committerMichael Albinus2020-12-14 19:30:01 +0100
commitc0c6cd2d5d7af82ddfd4d8d080d0aa8d7882d293 (patch)
tree176900038c02b3fcc984969464e51ce4aeb3f138
parent47a854bf24c8a36bf1e8ac32c8b5c9ebcba1d90a (diff)
downloademacs-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.texi11
-rw-r--r--etc/NEWS61
-rw-r--r--lisp/net/ange-ftp.el2
-rw-r--r--lisp/net/tramp-cmds.el3
-rw-r--r--lisp/net/tramp-compat.el5
-rw-r--r--lisp/net/tramp-sh.el13
-rw-r--r--lisp/net/tramp.el113
-rw-r--r--src/fileio.c6
-rw-r--r--test/lisp/net/tramp-tests.el27
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}.
129This is a subcategory of @code{file-error}. It happens, when a file 129This is a subcategory of @code{file-error}. It happens, when a file
130could not be watched for changes. @xref{File Notifications}. 130could not be watched for changes. @xref{File Notifications}.
131 131
132@item remote-file-error
133This is a subcategory of @code{file-error}, which results from
134problems in accessing a remote file. @xref{Remote Files,,, emacs, The
135GNU Emacs Manual}. Often, this error appears when timers, process
136filters, process sentinels or special events in general try to access
137a remote file, and collide with another remote file operation. In
138general it is a good idea to write a bug report. @xref{Reporting
139Bugs,,, 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
134This is a subcategory of @code{file-error}, which results from 143This is a subcategory of @code{remote-file-error}, which results from
135problems in accessing a remote file using ftp. @xref{Remote Files,,, 144problems in accessing a remote file using ftp. @xref{Remote Files,,,
136emacs, The GNU Emacs Manual}. 145emacs, The GNU Emacs Manual}.
137 146
diff --git a/etc/NEWS b/etc/NEWS
index 05274a2d6c6..87463372d57 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -89,7 +89,7 @@ useful on systems such as FreeBSD which ships only with "etc/termcap".
89This is controlled by the new variable 'scroll-minibuffer-conservatively'. 89This is controlled by the new variable 'scroll-minibuffer-conservatively'.
90 90
91In addition, there is a new variable 91In 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
93ad-hoc auto-scrolling when resizing minibuffer windows. It has been 93ad-hoc auto-scrolling when resizing minibuffer windows. It has been
94found that its heuristic can be counter productive in some corner 94found that its heuristic can be counter productive in some corner
95cases, tho the cure may be worse than the disease. This said, the 95cases, 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.
307Instead you need to do 'emacs -f dun-batch' to start the game in 307Instead you need to do "emacs -f dun-batch" to start the game in
308batch mode. 308batch 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
527If non-nil (the default), create registry entries for all messages. 526If non-nil (the default), create registry entries for all messages.
528If nil, don't automatically create entries, they must be created 527If nil, don't automatically create entries, they must be created
529manually. 528manually.
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 "%]".
533Four new options introduced in customisation group 532Four 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 "%["
538and '%]' specs in the summary line format. '%[' will normally display 537and "%]" specs in the summary line format. "%[" will normally display
539the value of 'gnus-sum-opening-bracket', but can also be 538the 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
541normally display the value of 'gnus-sum-closing-bracket', but can also 540normally display the value of 'gnus-sum-closing-bracket', but can also
542be 'gnus-sum-closing-bracket-adopted' for the adopted articles. 541be '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
1135for embedded images into svg. ':base-uri' is supported for both file 1134for embedded images into svg. ':base-uri' is supported for both file
1136and data svg images. 1135and 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
1141relatively to 'file-name-directory' of the ':base-uri' svg image property. 1140relatively to 'file-name-directory' of the ':base-uri' svg image property.
1142This works much faster then 'svg-embed'. 1141This works much faster then 'svg-embed'.
@@ -1256,8 +1255,8 @@ project's root directory, respectively.
1256So typing 'C-u RET' in the "*xref*" buffer quits its window 1255So typing 'C-u RET' in the "*xref*" buffer quits its window
1257before navigating to the selected location. 1256before 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'.
1260So far Grep and ripgrep are supported. ripgrep seems to offer better 1259So far 'grep' and 'ripgrep' are supported. 'ripgrep' seems to offer better
1261performance in certain cases, in particular for case-insensitive 1260performance in certain cases, in particular for case-insensitive
1262searches. 1261searches.
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'.
1447This is like 'this-command', but is bound recursively when entering 1445This is like 'this-command', but it is bound recursively when entering
1448the minibuffer. 1446the 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
1767The new command 'lisp-data-mode' enables a major mode for buffers 1764The new command 'lisp-data-mode' enables a major mode for buffers
1768composed of Lisp symbolic expressions that do not form a computer 1765composed of Lisp symbolic expressions that do not form a computer
1769program. The ".dir-locals.el" file is automatically set to use this 1766program. The ".dir-locals.el" file is automatically set to use this
1770mode, as are other data files produced by Emacs. 1767mode, as are other data files produced by Emacs.
1771 1768
1772** hierarchy.el 1769** hierarchy.el
1773
1774It's a library to create, query, navigate and display hierarchy structures. 1770It'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
1781options they provide. 1777options they provide.
1782 1778
1783** Dictionary mode 1779** Dictionary mode
1784 1780This is a mode for searching a RFC 2229 dictionary server.
1785This is a mode for searching a RFC 2229 dictionary 1781'dictionary' opens a buffer for starting operations.
1786server. 'dictionary' opens a buffer for starting 1782'dictionary-search' performs a lookup for a word. It also supports a
1787operations. 'dictionary-search' performs a lookup for a word. It also 1783'dictionary-tooltip-mode' which performs a lookup of the word under
1788supports a 'dictionary-tooltip-mode' which performs a lookup of the 1784the mouse in 'dictionary-tooltip-dictionary' (which must be customized
1789word under the mouse in 'dictionary-tooltip-dictionary' (which must be 1785first).
1790customized 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'.
2164If this variable is non-nil, character syntax is used for printing 2159If this variable is non-nil, character syntax is used for printing
2165numbers when this makes sense, such as '?A' for 65. 2160numbers when this makes sense, such as '?A' for 65.
2166 2161
2162** New error 'remote-file-error', a subcategory of 'file-error'.
2163It is signaled if a remote file operation fails due to internal
2164reasons, and could block Emacs. It does not replace 'file-error'
2165signals for the usual cases. Timers, process filters and process
2166functions, which run remote file operations, shall protect themselves
2167against this error.
2168
2169If such an error occurs, please report this as bug via 'M-x report-emacs-bug'.
2170Until 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."
159This includes password cache, file cache, connection cache, buffers." 159This 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.
4916If there is just some editing, retry it after 5 seconds." 4917If 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.
2371Together with `tramp-locker', this implements a locking mechanism
2372preventing reentrant calls of Tramp.")
2373
2374(defvar tramp-locker nil
2375 "If non-nil, then a caller has locked Tramp.
2376Together with `tramp-locked', this implements a locking mechanism
2377preventing 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.
4474Mostly 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.
4504This is needed in order to hide `last-coding-system-used', which is set 4493This 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.
6325If a file name matches REGEXP, all I/O on that file is done by calling 6331If 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.
6237Such requests could arrive from timers, process filters and 6238Such requests could arrive from timers, process filters and
6238process sentinels. They shall not disturb each other." 6239process 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