showkey
showkey

Reputation: 300

Why wait can't work for reader process in a named pipe?

wait in bash is for process to change state.In the following bash script,create a named pipe,and open 5 process to write data stream in it ,and open 1 process to read data stream from it into other file.

cat pipe.sh
fifo_file=fifo.pipe
mkfifo $fifo_file
exec 6<>$fifo_file
rm $fifo_file

DateWrite ()
{
    i=0
    while [[ $i -lt 200 ]]
    do
        str=`date`
        i=$(( i+1 ))
        echo "$i $str"
    done
}

writers=()
for  (( i=0; i<5; i++ ))
do 
    DateWrite >&6  & 
    echo "add a writer process pid  $!"
    writers+=($!)
done


while read date_time
do
    echo $date_time >> output.file 
done  <&6  &
reader=$!

for writer in "${writers[@]}" 
do
    wait "$writer"
    echo "the status of writer process pid $writer changed"   
done

echo "reader process pid is $reader"
wait  "$reader"
echo "the status of reader process pid $reader changed"   

exec 6<&-

To check the wait command in pipe.sh with bash pipe.sh.

add a writer process pid  4749
add a writer process pid  4750
add a writer process pid  4751
add a writer process pid  4752
add a writer process pid  4753
the status of writer process pid 4749 changed
the status of writer process pid 4750 changed
the status of writer process pid 4751 changed
the status of writer process pid 4752 changed
the status of writer process pid 4753 changed
reader process pid is 4754

The info list don't contain

the status of reader process pid 4754 changed

The statement wait "$reader" execute in a infinite while loop,it is normal that wait can't work.
If i delete the tow lines:

wait  "$reader"
echo "the status of reader process pid $reader changed"   

And execute bash pipe.sh :

add a writer process pid  19670
add a writer process pid  19671
add a writer process pid  19673
add a writer process pid  19674
add a writer process pid  19675
the status of writer process pid 19670 changed
the status of writer process pid 19671 changed
the status of writer process pid 19673 changed
the status of writer process pid 19674 changed
the status of writer process pid 19675 changed
reader process pid is 19676

Search the pid 19676 in console.

ps aux |grep '[p]ipe'
debian   19676  0.0  0.0  16516  2100 pts/1    S    19:54   0:00 bash pipe.sh

The reader process created in pipe.sh is still running when pipe.sh is finished.
I don't want to change wait "$reader" into kill "$reader" in pipe.sh.
Is there a way to know echo $date_time have read the end of pipe,and send a signal to close read process?

@Philippe and all friends here ,sleep 1; echo q >&6,maybe the time interval is so short.Let's suppose more complicated case:

while read date_time
do
    test "$date_time" = q && exit
    echo $date_time >> output.file 
    bash_some_code_do_some_thing
done  <&6  &

The running time for bash_some_code_do_some_thing is longer than 10 seconds ,at least 10 seconds ,not at most 10 seconds,and you can't estimate the precise time.You can't write such code as

sleep 10; echo q >&6

or

sleep 100; echo q >&6 #what if the running time is 200 seconds more?

How to solve the case then?

Upvotes: 0

Views: 230

Answers (1)

Philippe
Philippe

Reputation: 26602

There is no way to send an EOF to a pipe opened read-write. One work-around is to send a quit command :

fifo_file=fifo.pipe
mkfifo $fifo_file
exec 6<>$fifo_file
rm $fifo_file

DateWrite ()
{
    i=0
    while [[ $i -lt 200 ]]
    do
        str=`date`
        i=$(( i+1 ))
        echo "$i $str"
    done
}

writers=()
for  (( i=0; i<5; i++ ))
do 
    DateWrite >&6  & 
    echo "add a writer process pid  $!"
    writers+=($!)
done


while read date_time
do
    test "$date_time" = q && exit
    echo $date_time >> output.file 
done  <&6  &
reader=$!

for writer in "${writers[@]}" 
do
    wait "$writer"
    echo "the status of writer process pid $writer changed"   
done

echo "reader process pid is $reader"
sleep 1; echo q >&6
wait  "$reader"
echo "the status of reader process pid $reader changed"   

exec 6<&-

Another way is to send TERM signal to the reader.

Upvotes: 1

Related Questions