Subject: bug#79079: 31.0.50; Piped command output is sometimes lost in Eshell

From: Jim Porter <[email-masked]>
Date: Sun, 27 Jul 2025 12:34:10 -0700

On 7/27/2025 12:14 PM, Paul Eggert wrote:
> From Jim's recent email it sounds like Eshell does not actually set up 
> a pipe when implementing "A | B", but instead does something else that 
> simulates a pipe. I don't know how the simulation works, but it sounds 
> like the simulated pipe cannot act like a real pipe when B closes its 
> end of the simulated pipe, A ignores SIGPIPE, and A writes to the 
> simulated pipe. With a real pipe A would get an EPIPE error, and I guess 
> that's not happening with the simulated pipe.

If we're being technical, Eshell does use pipes for its pipe operator, 
but there's an additional layer of indirection that makes it difficult 
to simulate the usual POSIX shell piping:

   process A -> stdout pipe -> process filter -> process-send-string -> 
stdin pipe -> process B

If 'process-send-string' fails, we raise a Lisp signal 
'eshell-pipe-broken', that tries to be as much like SIGPIPE as we can. 
Because of this indirection though, process A won't see an EPIPE/SIGPIPE 
at the normally-expected time, hence my comment in esh-proc.el:

            ;; The output pipe broke, so send SIGPIPE to the
            ;; process.  NOTE: Due to the additional indirection
            ;; of Emacs process filters, the process will likely
            ;; see the SIGPIPE later than it would in a regular
            ;; shell, which could cause problems.  For cases
            ;; where this matters, using an external pipe
            ;; operator (`*|') may work instead.

Luckily, this bug is really about what happens with process B in the 
pipeline, so I won't have to make any further changes to the process A 
side of things (at least not yet).