Home > OS >  In bash script, what happens when a signal is trapped
In bash script, what happens when a signal is trapped

Time:04-11

Suppose I am running the following example saved as hello.sh

#!/bin/bash
hello() {
    echo "hello"
}

trap "hello" INT
sleep 100
echo "end"

and in shell I start hello.sh. After 1 second I press Ctrl-C.

Please treat sleep as any long-run process that I started.

Here are my questions:

  1. When SIGINT is generated, is it delivered to sleep directly or to the shell script?
  2. If it is the second, can I let sleep has a chance to handle the SIGINT and do not propagate to its parent hello.sh?
  3. If it is the first, what is the status of sleep after the hello function is finished?

My tests made me feel that the following occurred in order

  1. sleep started to run
  2. hello.sh received the signal
  3. function hello started to run
  4. function hello finished
  5. echo "end" started to run
  6. the script exits.

But at which stage the sleep process exits and because of what (e.g. the SIGINT stopped the sleep process?)

CodePudding user response:

$ cat foo.sh
_sigint()
{
    echo "received SIGINT"
}

trap _sigint INT

sleep 10000
echo "status=$?"
$ bash foo.sh              # <-- start foo.sh and then press CTRL-C
^Creceived SIGINT
status=130

Some explanation:

  • sleep runs as a child process of bash. bash and sleep are running in the same process group which is now the foreground process group.

  • When CTRT-C is pressed, it'll generate SIGINT and the signal will be sent to all processes in the foreground process group so both bash and sleep will receive SIGINT.

  • According to bash manual (can also see man bash)

    If bash is waiting for a command to complete and receives a signal for which a trap has been set, the trap will not be executed until the command completes.

    So here bash would wait for sleep to be killed (The default SIGINT behavior is to terminate the process. See signal(7)) first and then bash runs its SIGINT trap.

  • According to bash manaul

    The return value of a simple command is its exit status, or 128 n if the command is terminated by signal n.

    The SIGINT is 2 (see kill -l) so sleep's exit status is 128 2=130.

  • Related