I'm confused about forwarding signals to child processes with traps. Say I have two scripts:
a.sh
#!/bin/bash
# print the process id
echo $$
cleanup() {
rv=$?
echo "cleaning up $rv"
exit
}
sleep 5
trap '' SIGTERM # trap cleanup SIGTERM
echo 'cant stop wont stop'
./b.sh
echo 'can stop will stop'
trap - SIGTERM
sleep 4
echo 'done'
b.sh
#!/bin/bash
sleep 4;
echo 'b done'
If I execute a.sh
and then from another window kill the process group with kill -- -PGID
, the SIGTERM is ignored and not passed on to b.sh
. But if I do trap cleanup SIGTERM
, the SIGTERM passes through and terminates b.sh
. Why is my trap passing the signal in one case and not the other?
This is interesting. Quoting man 7 signal
:
A child created via fork(2) inherits a copy of its parent's signal dispositions. During an execve(2), the dispositions of handled signals are reset to the default; the dispositions of ignored signals are left unchanged.
In your case, the child always receives TERM
by virtue of being in the same process group. The problem is, what does it do with it.
When the parent ignores TERM
, by the rule above, so does the child, so the child survives. When the parent catches TERM
, the child's handler will be reset, and it will die as the default action.