Consider the below script
#!/usr/bin/bash
chan=/tmp/pipe.$$
mkfifo $chan
{
for x in a b c d e
do
echo $x > $chan
done
} &
for y in 1 2 3 4 5
do
x=$(cat $chan)
echo "var $x = $y ;"
done
rm $chan
Does not seem to work as expected. E.g.
❯ ./testpipe.sh
var a
b
c = 1 ;
^C
Does the echo not supposed to wait if there are no readers for the fifo? When I do this in terminal, it hangs as expected
❯ mkfifo /tmp/pipe
❯ echo 1 > /tmp/pipe
^C
Why does it behave differently in the script?
Update
I changed to use fds instead of opening every time.
#!/usr/bin/bash
chan=/tmp/pipe.$$
mkfifo $chan
{
exec 5>"$chan"
for x in a "ba ba ba baanannna" c d e
do
echo $x >&5
done
} &
exec 6<"$chan"
for y in 1 2 3 4 5
do
read -u 6 x
echo "var $x = $y ;"
done
rm $chan
Not sure I fixed it or just made it more rare for the race to occur.
❯ ./testpipe.sh
var a = 1 ;
var ba ba ba baanannna = 2 ;
var c = 3 ;
var d = 4 ;
var e = 5 ;
Update 2
Don't need a fifo at all. Just proc substitution is enough to run something in background and read from it when required. Tested adding sleep before and after in both producer and consumers. Seems to work fine. Likely no race.
#!/usr/bin/bash
produce()
{
for x in a "ba ba ba baanannna" "more space" d e
do
echo "$x"
done
}
exec {fd}< <(produce)
for y in 1 2 3 4 5
do
read -u $fd x
echo "var $x = $y ;"
done