diff options
Diffstat (limited to 'lisp')
-rw-r--r-- | lisp/eshell/esh-io.el | 12 | ||||
-rw-r--r-- | lisp/eshell/esh-proc.el | 31 |
2 files changed, 35 insertions, 8 deletions
diff --git a/lisp/eshell/esh-io.el b/lisp/eshell/esh-io.el index fc1124561a5..3644c1a18b5 100644 --- a/lisp/eshell/esh-io.el +++ b/lisp/eshell/esh-io.el @@ -150,6 +150,8 @@ not be added to this variable." :risky t :group 'eshell-io) +(define-error 'eshell-pipe-broken "Pipe broken") + ;;; Internal Variables: (defvar eshell-current-handles nil) @@ -481,10 +483,12 @@ Returns what was actually sent, or nil if nothing was sent." (goto-char target)))))) ((eshell-processp target) - (when (eq (process-status target) 'run) - (unless (stringp object) - (setq object (eshell-stringify object))) - (process-send-string target object))) + (unless (stringp object) + (setq object (eshell-stringify object))) + (condition-case nil + (process-send-string target object) + ;; If `process-send-string' raises an error, treat it as a broken pipe. + (error (signal 'eshell-pipe-broken target)))) ((consp target) (apply (car target) object (cdr target)))) diff --git a/lisp/eshell/esh-proc.el b/lisp/eshell/esh-proc.el index bb2136c06cc..ed37de85f7a 100644 --- a/lisp/eshell/esh-proc.el +++ b/lisp/eshell/esh-proc.el @@ -386,8 +386,27 @@ output." (let ((data (nth 3 entry))) (setcar (nthcdr 3 entry) nil) (setcar (nthcdr 4 entry) t) - (eshell-output-object data nil (cadr entry)) - (setcar (nthcdr 4 entry) nil))))))))) + (unwind-protect + (condition-case nil + (eshell-output-object data nil (cadr entry)) + ;; FIXME: We want to send SIGPIPE to the process + ;; here. However, remote processes don't + ;; currently support that, and not all systems + ;; have SIGPIPE in the first place (e.g. MS + ;; Windows). In these cases, just delete the + ;; process; this is reasonably close to the + ;; right behavior, since the default action for + ;; SIGPIPE is to terminate the process. For use + ;; cases where SIGPIPE is truly needed, using an + ;; external pipe operator (`*|') may work + ;; instead (e.g. when working with remote + ;; processes). + (eshell-pipe-broken + (if (or (process-get proc 'remote-pid) + (eq system-type 'windows-nt)) + (delete-process proc) + (signal-process proc 'SIGPIPE)))) + (setcar (nthcdr 4 entry) nil)))))))))) (defun eshell-sentinel (proc string) "Generic sentinel for command processes. Reports only signals. @@ -416,8 +435,12 @@ PROC is the process that's exiting. STRING is the exit message." (lambda () (if (nth 4 entry) (run-at-time 0 nil finish-io) - (when str (eshell-output-object str nil handles)) - (eshell-close-handles status 'nil handles))))) + (unwind-protect + (when str + (eshell-output-object + str nil handles)) + (eshell-close-handles + status 'nil handles)))))) (funcall finish-io))))) (eshell-remove-process-entry entry)))) (eshell-kill-process-function proc string))))) |