First, you should know that
kill 0 send the signal to all process in current process group. (see kill(1) - Linux man page) My guess is that it is killing more than it should. This is why
wait is not waiting, it is being terminated for some reason. My best bet to solve this problem is to iterate over running jobs from
jobs -pr killing one by one: this way I assure the signal is sent only to child processes in that moment and nothing more.
To get this to work I did several tests, but I was stuck on sending SIGINT to child processes. They simple don't react to it! Searching the web I've found this answer on Stack Overflow:
So the real problem is that you cannot send SIGINT from one script to other, because in non-interactive shells the signal is ignored. I was not able to workaround this issue (using
bash -i to call the child script does not to work).
I know you probably want to send SIGINT and wait for the child processes to shutdown gracefully, but if you do not mind to use SIGTERM (or any other signal but SIGINT) this is the best script I wrote:
trap 'killall' INT
echo '**** Shutting down... ****'
for i in $(jobs -pr); do
kill -TERM $i
cat # wait forever
To test, I've created this
trap 'killall' TERM
echo "Started... $$" >> file.txt
# shutting down gracefully
echo "Finished... $$" >> file.txt
exit # don't forget this!
# infinite loop
while true; do echo loop >/dev/null ; done
In this last script I did not use
sleep function because it creates a new process that was staying on memory even after the script finishes. In your script, you can call new processes but you should assure to broadcast the SIGTERM (or any other signal you've used) to all of them.