I try really hard to understand what I am doing wrong and why?
I have a launch.sh
script which launches process.sh
.
launch.sh
#!/bin/bash
while true; do
./process.sh
done
process.sh
#!/bin/bash
function signalHandler() {
for i in {1..2}; do
sleep 0.1s
echo "process.sh: cleanup $i"
done
exit 130
}
trap "signalHandler" "SIGINT"
while true; do
sleep 1s
done
when I run
./launch.sh &
and then kill it with
kill -s SIGINT -$!
where $!
gets the PID of the last command (launch.sh) and the minus sends the signal to all childs, then launch.sh
continues.
Why?
I expected the following behavior (according to this blog Signal & Bash) :
the shell A with the script launch.sh
running in background gets interrupted, Bash waits till process.sh
finishes. Since process.sh
returns abnormally (exit 130) due to the signal handler in process.sh
, shell A should exit. Why does it not?
If this child’s status indicates it exited abnormally due to that signal, the shell cleans up, removes its signal handler, and kills itself again to trigger the OS default action (abnormal exit). Alternatively, it runs the script’s signal handler as set with trap, and continues.
Best Answer
First,
exit 130
is not an abnormal exit. It is a normal exit, with exit status 130. As can be seen fromman 3 wait
(POSIX):WIFEXITED
checks normal exit, andWIFSIGNALLED
is termination due to an uncaught signal. Since these are mutually exclusive, anexit 130
is normal.That the exit status is 130 when a process dies by SIGINT is because bash sets it to be 130 outside of the process because it detected an exit due to SIGINT: Why does bash set $? (exit status) to non-zero on Ctrl-C or Ctrl-Z?
Second, a process that handles SIGINT and then dies should kill itself with SIGINT. Greg's wiki (an excellent resource for shell stuff) has a note on this:
Now, if you changed the
exit 130
to:You'd see the expected behaviour.