That is only true in simple cases though as outlined below.
Sending signal INT is the equivalent to sending signal 2 (on most UNIX versions at least) and signals are sent via the kill command in shells or kill functions in programming languages.
Simple Case: the same
The phrase above refers to the issue that in an interactive shell pressing Ctrl-C sends signal INT to the current foreground process.In the simple cases below pressing Ctrl-C or 'kill -2' are equivalent.
Example:
trap1.sh: #!/bin/sh # Catch signal 0 trap "echo exiting" 0 # Catch signal 2 trap "echo trapped;exit" 2 # Forever loop while : ; do sleep 1; done echo DONE # Run trap1.sh and interrupt with Ctrl-C % trap1.sh ^Ctrapped exiting # Run trap1.sh and determine its pid in another terminal and do kill -2 pid % trap1.sh trapped exitingi.e. both times the program gets interrupted, a trap message and final exit message are printed, the final DONE is never reached.
Tricky case: different behaviour
Some might have wondered about the example above. Why not replace the while loop with a simple sleep 60? So the script would be this:trap2.sh: #!/bin/sh # Catch signal 0 trap "echo exiting" 0 # Catch signal 2 trap "echo trapped;exit" 2 # Sleep for some time sleep 60 echo DONE # Run trap2.sh and interrupt with Ctrl-C: same behaviour as before: the script gets killed % trap2.sh ^Ctrapped exiting # Run trap2.sh and determine its pid in another terminal and do kill -2 pid # no success this time, the script continues to run. # It will end only after 60 seconds sleep time have passed !!! % trap2.sh trapped exitingSo why didn't kill -2 cancel the script?
The signal was sent to the script's process but the spawned 'sleep' process was not affected. A ptree would have shown
12632 /bin/sh trap2.sh 12633 sleep 60
Ctrl-C on the other hand sends the signal to more than one process: all sub processes of the foreground process are also notified (except background processes). That is the important difference between these two approaches.
Here's a program to test this.
# The script below starts 3 processes as seen in ptree: # 64473 /bin/sh trap3.sh # 64474 /bin/sh ./trap3.sh number2 # 64475 sleep 50 trap3.sh: #!/bin/sh ID="$1" [ -z "$ID" ] && ID="number1" trap "echo $ID exiting" 0 trap "echo $ID trapped 2;exit" 2 [ "$ID" = "number1" ] && ./trap3.sh number2 sleep 50 # Run trap3.sh and interrupt with Ctrl-C # all processes are killed and both trap.sh processes report their trap messages % trap3.sh ^Cnumber2 trapped 2 number2 exiting number1 trapped 2 number1 exiting # Run trap3.sh and and determine its pid in another terminal and do kill -2 pid # After 50 seconds you'll see the trap 0 message from the second trap process # and the trap 2 and trap 0 messages from the first trap process # So: # the second trap3.sh process was never interrupted !!! # the first trap3.sh process waited until its sub process finished (despite receiving sig 2) % trap3.sh number2 exiting number1 trapped 2 number1 exitingSo watch out when testing program signal handling: if your program reacts as expected to a manual Ctrl-C it might not do the same to a kill signal coming from other processes.
Thanks for this post exactly the problem I was running into
ReplyDelete