I have a Bourne shell (/bin/sh) script (for portability) that wants to monitor another program. It should start the other program, then wait for it to exit. When the second program exits, it does some final work and exits itself. The catch is that the script needs to also respond to a signals (eg USR2) and do some work when those signals show up.
My naive implementation is:
#! /bin/sh
echo $$
trap 'echo Respond to USR2' USR2
/bin/sleep 120 &
pid=$!
wait $pid
echo $pid exited with $?
echo Doing final cleanup
This doesn't work. If I send the shell SIGUSR2, the trap fires as expected, but wait also finishes, returning 140. The /bin/sleep continues on its merry way. Typical output:
28849
Respond to USR2
28850 exited with 140
Doing final cleanup
This behaviour is consistent between dash and bash, the two Bourne shell derivatives I have convenient access to.
My current work around is to spin loop waiting for the child PID to disappear, probing with kill. Spin looping seems wasteful, and enlarges the window where my script might erroneously be waiting for the wrong process if PIDs are being rapidly reused.
#! /bin/sh
echo $$
trap 'echo Respond to USR2' USR2
/bin/sleep 15 &
pid=$!
while /bin/kill -0 $pid 2> /dev/null; do
echo waiting...
sleep 2
done
echo Doing final cleanup
Is there a better solution given my goal of simultaneously waiting for another process to exit and being able to respond to signals?