Say I have these two bash scripts:
/tmp/trapper:
#!/bin/bash
trap 'echo trapper: ignoring USR1' USR1
"$(dirname $0)"/usr1er & p=$!
sleep 1
echo trapper: now killing usr1er
kill $p
echo trapper: sleeping
sleep 1
echo trapper: reached end of trapper
/tmp/usr1er:
#!/bin/bash
trap 'echo "usr1er: EXIT received, sending USR1"; kill -USR1 0' EXIT
while sleep 1;do echo usr1er: sleeping;done
trapper is supposed to trap USR1 and simply ignore it. It starts usr1er, which kills its process group with the USR1 signal. Now, if I start trapper as a script on its own from an interactive shell, it kills usr1er and exits normally:
$ /tmp/trapper; echo done
trapper: now killing usr1er
trapper: sleeping
usr1er: EXIT received, sending USR1
/tmp/trapper: line 9: 16596 Terminated "$(dirname $0)"/usr1er
trapper: ignoring USR1
trapper: reached end of trapper
done
While if I try $(/tmp/trapper)
, it exits the whole shell. Similarly, if I make a separate script that calls /tmp/trapper
, like /tmp/outer
:
#!/bin/bash
"$(dirname $0)"/trapper
echo outer: reached end of outer
it gets killed without printing the "reached end of outer":
$ /tmp/outer
trapper: now killing usr1er
trapper: sleeping
usr1er: EXIT received, sending USR1
User defined signal 1
/tmp/trapper: line 9: 23544 Terminated "$(dirname $0)"/usr1er
User defined signal 1
trapper: ignoring USR1
trapper: reached end of trapper
Why?
Try this change
/tmp/usr1er:
Handled TERM signal instead of EXIT & sent USR1 to
$PPID
instead of0
It seems that
$()
does not start the process with a separate process group / PGID (apparantly for makingC-c
work).Also, any non-interactive shell will also not start separate PGID's for their children (unless you turn on job control with set -m):
Note that "done" is not printed, the outer bash script, which doesn't trap USR1, is killed while trapper keeps on living until the end.
You can check the PGID of each process by putting
ps -o %p%r%c -p$$
in the scripts: