As described in the title, I am trying to run a program from a bash script, but it is getting stopped when I background the script. However, this is only the case when I redirect its stdin to a named pipe and keep the pipe open from the same script.
Here is a minimal reproduction of the behavior:
In foo.sh
I have:
#!/bin/bash
while true
do
echo "Running"
sleep 1
done
In bar.sh
I have:
#!/bin/bash
rm -f pipe
mkfifo pipe
./foo.sh < pipe & # Let's say foo.sh has PID 42
cat > pipe
In the shell I run ./bar.sh
, which repeatedly prints “Running” as expected. Then I background bar.sh
and it stops printing. If I run kill -CONT 42
it starts printing again.
However, if I don’t redirect stdin to the pipe (i.e. replace ./foo.sh < pipe &
with just ./foo.sh &
), when I background bar.sh
it does not stop printing.
Can someone explain this difference in behavior to me, and if possible explain how I can prevent foo.sh
from stopping when it gets its stdin from the named pipe?
7
cat > pipe
tries to read from stdin, so it gets stopped when it runs in the background.
The reason this doesn’t happen when you don’t redirect the input of foo.sh
to the pipe is that the shell is blocked trying to open the pipe for writing. That won’t succeed until another process opens it for reading, and it doesn’t start cat
until it opens the pipe.
When I reproduce the error, ps
shows that both foo.sh
and bar.sh
are in T
(stopped) state:
PID TTY STAT TIME COMMAND
1888904 pts/1 T 0:00 /bin/bash ./bar.sh
1888907 pts/1 T 0:00 /bin/bash ./foo.sh
1888908 pts/1 T 0:00 cat
1888924 pts/1 T 0:00 sleep 1
So it appears that the entire process group is being stopped, not just the cat
process.
The symptons are different on MacOS than Linux. On the Mac, I get the following error when I put bar.sh
in the background:
cat: stdin: Interrupted system call
and Running
keeps on printing. I don’t know if this is due to OS differences or the older version of bash
.
7