6

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.

1 Answer 1

5

First, exit 130 is not an abnormal exit. It is a normal exit, with exit status 130. As can be seen from man 3 wait (POSIX):

   If  the  information  pointed  to  by  stat_loc was stored by a call to
   waitpid()  that  specified  the  WUNTRACED     and  WCONTINUED   flags,
   exactly one of the macros WIFEXITED(*stat_loc), WIFSIGNALED(*stat_loc),
   WIFSTOPPED(*stat_loc),  and WIFCONTINUED(*stat_loc)  shall evaluate  to
   a non-zero value.

WIFEXITED checks normal exit, and WIFSIGNALLED is termination due to an uncaught signal. Since these are mutually exclusive, an exit 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:

If you choose to set up a handler for SIGINT (rather than using the EXIT trap), you should be aware that a process that exits in response to SIGINT should kill itself with SIGINT rather than simply exiting, to avoid causing problems for its caller. Thus:

trap 'rm -f "$tempfile"; trap - INT; kill -INT $$' INT

Now, if you changed the exit 130 to:

trap - INT
kill -INT $$

You'd see the expected behaviour.

3
  • do you know how to exit a python script in the bahvior you described, meaning killing itself i think sys.exit(1) in the signal handler in python is wrong as well
    – Gabriel
    Feb 17, 2016 at 9:22
  • 1
    @Gabriel os.kill(os.getpid(), signal.SIGINT), perhaps?
    – muru
    Feb 18, 2016 at 1:44
  • yes! thats the solution
    – Gabriel
    Feb 18, 2016 at 10:25

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .