`read -d x` hangs when run under gnu parallel, even if input is redirected

Russell Harmon <[email protected]> Tue, 2 Dec 2025 06:15:45 -0800
Newsgroups gmane.comp.shells.zsh.user
Message-ID <CA+zrezQe4G8X5fUb_vc5yAm1q19Y-7Sh+OL7sHxuB_4tYhvcMQ@mail.gmail.com>
Hi all,

I'm trying to read a null-delimited file from a script launched via
GNU parallel. E.g. something like this:

$ parallel -qu -- zsh -fc 'read -d x </dev/random' ::: a

However the above hangs forever.

I *think* the reason is that when zsh initializes, it captures (in fd
10) a copy of the controlling tty's fd, and then `read` attempts to
perform `tcsetattr` on it, however when invoked under `parallel`,
there is no controlling tty, so tcsetattr causes a SIGTTOU signal to
be delivered.

I've been looking through the sources to bin_read and I can't quite
piece together why it's attempting to call tcsetattr on fd 10, but I'm
certain it's happening because if I attach gdb to the hung shell, I
can see the call:

$ gdb /bin/zsh -ex 'attach 2960142'
...
Program received signal SIGTTOU, Stopped (tty output)
__tcsetattr (fd=10, optional_actions=1, termios_p=0x7ffecf7cb5c0)
...

Running parallel with --tty works around the issue:

$ parallel --tty -qu -- zsh -fc 'read -d x </dev/random' ::: a

I've been trying to reproduce without GNU parallel using

$ true | (setsid -w zsh -fc 'read -d x < /dev/random' </dev/null) |& cat

... but it's not been reproducing this way, so I'm missing some crucial detail.

Is it obvious to someone else what's wrong?