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

From: Daniel Mendler <[email-masked]>
Date: Wed, 23 Jul 2025 20:17:47 +0200

Jim Porter <[email-masked]> writes:

> On 7/23/2025 8:52 AM, Jim Porter wrote:
>> I'm not able to reproduce this locally, but if you first run "eshell-debug
>> process", that will log a bunch of process-related information to the buffer
>> "*eshell last cmd*". That would probably have some details that at least show
>> where the I/O went missing.
>
> After a few more tries, I was able to reproduce this very rarely. Does the
> following patch help?

Thanks for looking into this so quickly and coming up with a patch! I
can check this earliest end of next week. Recompiling Emacs always takes
me a little bit longer than simply evaluating some Elisp.

> Eli: maybe you can help with some of the details here. In process.c, when we
> write to a process, we handle EPIPE errors by calling 'deactivate_process'.
> However, that can lead to us dropping any data written *by* that process, since
> we don't call the process's filter function for any remaining output still in
> our internal buffer.
>
> I think in this case, we'd just want to let the rest of our code handle
> deactivating the process in the usual way. That helps fix this bug, plus I think
> it makes sense in general. If a process closes stdin, I believe we'd get the
> EPIPE error, but that process might want to continue working (though it does
> mean that you could only interact with that process via signaling it).

Maybe this also needs some test to avoid regressions? Did you find a way
to reliably reproduce the problem?

> Does that make sense?
>
> diff --git a/src/process.c b/src/process.c
> index e61ec425f7e..258bee21b5e 100644
> --- a/src/process.c
> +++ b/src/process.c
> @@ -6876,7 +6876,6 @@ send_process (Lisp_Object proc, const char *buf, ptrdiff_t len,
>                   p->raw_status_new = 0;
>                   pset_status (p, list2 (Qexit, make_fixnum (256)));
>                   p->tick = ++process_tick;
> -                 deactivate_process (proc);
>                   error ("Process %s no longer connected to pipe; closed it",
>                          SDATA (p->name));
>                 }