I have migrated some scripts from ksh to bash and I have observed very strange behavior in bash. I was able to reduce to a very short snippet.
echo first test
LC_ALL=C xclock &
Active_pid=$!
sleep 1
kill -9 $Active_pid
sleep 1
echo second test
LC_ALL=C xclock &
Active_pid=$!
sleep 1
trap "echo Signal SIGKILL caught" 9
kill -9 $Active_pid
sleep 1
The output is
first test
./mig_bash.sh: line 15: 4471 Killed LC_ALL=C xclock
second test
My problem was the production of the trace in the first test. I have tried to see if a signal was received. By trial and error, I wrote the "second test" that solve my problem. I do not understand it. How this removes the trace of the first test without executing echo Signal SIGKILL
?
I am completely lost.
The SIGTERM signal is a generic signal used to cause program termination. Unlike SIGKILL , this signal can be blocked, handled, and ignored.
There is no automatic propagation of signals (SIGTERM or otherwise) to children in the process tree.
The Kill menu item enables you to kill a process quickly by sending it a kill (9) signal.
kill ends a process by sending it a signal. The default signal is SIGTERM. kill is a built-in shell command.
I couldn't find anything in the bash documentation that would explain the observed behavior, so I turned to the source code. Debugging lead to the function notify_of_job_status()
. The line that prints the message about a killed subprocess can be reached only if all of the following conditions hold:
disown
-ed)signal_is_trapped (termsig) == 0
check)Demonstration:
$ cat test.sh
echo Starting a subprocess
LC_ALL=C sleep 100 &
Active_pid=$!
case "$1" in
disown) disown ;;
trapsigkill) trap "echo Signal SIGKILL caught" 9 ;;
esac
sleep 1
kill -9 $Active_pid
sleep 1
echo End of script
$ # Demonstrate the undesired message
$ bash test.sh
Starting a subprocess
test.sh: line 14: 15269 Killed LC_ALL=C sleep 100
End of script
$ # Suppress the undesired message by disowning the child process
$ bash test.sh disown
Starting a subprocess
End of script
$ # Suppress the undesired message by trapping SIGKILL in the parent shell
$ bash test.sh trapsigkill
Starting a subprocess
End of script
$ # Suppress the undesired message by using an interactive shell
$ bash -i test.sh
Starting a subprocess
End of script
How this removes the trace of the first test without executing
echo Signal SIGKILL
?
The trap is not executed since the KILL
signal is received by the sub-process rather than the shell process for which the trap has been set. The effect of the trap on the diagnostics is in the (somewhat arguable) logic in the notify_of_job_status()
function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With