Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Bug: reading from tty inside process substitution



On Tue, Nov 14, 2023 at 7:33 PM Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
>
> > read foo < <(read bar; echo $bar) </dev/tty
>
> That still doesn't respond to interrupts

So what seems to be going on here is that the shell enters
waitonejob() via waitjobs() from execpline().  At that point it has a
nonzero auxprocs pointer, so it calls zwaitjob() which for the same
reason eventually calls signal_suspend(SIGCHLD), which adds SIGINT to
the ignored signals to allow the presumed foreground child to handle
the signal.

The problem is that by that point the auxiliary "foreground" process
-- the process substitution -- has already exited.  It was promptly
reaped, but zwaitjob() is in a loop waiting with SIGINT still blocked
for the parent's jn->stat to be updated to either 0 or STAT_DONE.
Trouble is, that parent is the multio loop, which is actively skipping
over interrupts and won't quit until EOF.

What about the following?  Is there some simple way to check that the
multio tty is the same tty as SHIN ?  Also, even with this in place,
something is still ignoring TSTP (^z), perhaps because "read foo" is
in the top-level interactive shell, so this can't be suspended.

diff --git a/Src/exec.c b/Src/exec.c
index 285d2c5ad..97823760f 100644
--- a/Src/exec.c
+++ b/Src/exec.c
@@ -2309,7 +2309,7 @@ closemn(struct multio **mfds, int fd, int type)
         for (i = 0; i < mn->ct; i++)
         while ((len = read(mn->fds[i], buf, TCBUFSIZE)) != 0) {
             if (len < 0) {
-            if (errno == EINTR)
+            if (errno == EINTR && !isatty(mn->fds[i]))
                 continue;
             else
                 break;

(This patch may not apply cleanly due to gmail ... I'll prepare a
proper one if deemed OK.)




Messages sorted by: Reverse Date, Date, Thread, Author