If I run a command like:
cat <(echo 1 | pv) | pv
cat <(echo 1 | pv) | less
cat <(echo 1 | pv) | cat
The command seems to run forever. Entering ^C
(SIGINT) kills the entire shell instead of just the commands executed. Why is this the case?
Relevant output of ps xf
from another shell on minimal case cat <(pv) | less
:
Ss /bin/bash
S+ \_ cat /dev/fd/XX
S | \_ /bin/bash
T | \_ pv
S+ \_ less
With these file descriptors open:
bash
0 -> /dev/pts/YY
1 -> /dev/pts/YY
2 -> /dev/pts/YY
255 -> /dev/pts/YY
cat /dev/fd/ZZ
0 -> /dev/pts/YY
1 -> pipe:[RRRRRRRR]
2 -> /dev/pts/YY
3 -> pipe:[QQQQQQQQ]
ZZ -> pipe:[QQQQQQQQ]
bash
0 -> /dev/pts/YY
1 -> pipe:[QQQQQQQQ]
2 -> /dev/pts/YY
255 -> /dev/pts/YY
pv
0 -> /dev/pts/YY
1 -> pipe:[QQQQQQQQ]
2 -> /dev/pts/YY
less
0 -> pipe:[RRRRRRRR]
1 -> /dev/pts/YY
2 -> /dev/pts/YY
3 -> /dev/tty
Using the original example, cat <(echo 1 | pv) | less
(this also happens when echo
is not a bash builtin but another program like dd if=/dev/zero bs=1 count=1
:
Ss /bin/bash
S+ \_ cat /dev/fd/63
S | \_ /bin/bash
T | \_ pv
S+ \_ less
bash
0 -> /dev/pts/18
1 -> /dev/pts/18
2 -> /dev/pts/18
255 -> /dev/pts/18
cat /dev/fd/63
0 -> /dev/pts/18
1 -> pipe:[36932796]
2 -> /dev/pts/18
3 -> pipe:[36929317]
63 -> pipe:[36929317]
bash
0 -> /dev/pts/18
1 -> pipe:[36929317]
2 -> /dev/pts/18
255 -> /dev/pts/18
pv
0 -> pipe:[36930391]
1 -> pipe:[36929317]
2 -> /dev/pts/18
less
0 -> pipe:[36932796]
1 -> /dev/pts/18
2 -> /dev/pts/18
3 -> /dev/tty
cat <(pv) | cat
– Mark Plotnick Jan 1 '16 at 19:03cat <(pv) | cat
, pv never gets a chance to read from stdin. It gets stopped with SIGTTOU very early on. Same behavior as in the larger examples. In fact, the code in pv's main explicitly sets TOSTOP on the tty that's on fd 2, with the comment "Set terminal option TOSTOP so we get signal SIGTTOU if we try to write to the terminal while backgrounded." As Mike said, bash may not be equipped to correctly handle job control signals inside a process substitution context. – Mark Plotnick Jan 5 '16 at 15:36cat <(echo 1 | pv 2> >(cat) ) | whatever
appears to work fine. – Mark Plotnick Jan 5 '16 at 16:02