6

Running bash 4.3 on Kubuntu Trusty 64 bit. Please see the following two files:

trapping-int.sh

#! /bin/bash
trap "echo Exiting" INT
cat </dev/urandom >/dev/null
echo Hello

trapping-exit.sh

#! /bin/bash
trap "echo Exiting" EXIT
cat </dev/urandom >/dev/null
echo Hello

Now upon hitting ^C, trapping SIGINT prints both Exiting and Hello whereas trapping EXIT prints Exiting only but with an extra newline:

$ ./trapping-int 
^CExiting
Hello
$ ./trapping-exit 
^CExiting

$

I would like to know the reason for the differing behaviour. Also, can I safely assume that EXIT is always called even if INT is given by ^C?

Commenting out the last line in both scripts causes trapping SIGINT to no longer print the Hello but trapping EXIT still prints the extra newline. I'd like to know the reason here too.

Thanks!

  • For what it's worth, I see this same behavior on Arch linux, 64 bit, bash 4.3.30(1)-release – Bruce Ediger Oct 25 '14 at 14:26
9

First, a summary of some facts about signals and the shell:

  • When you press CTRL+C at the keyboard, a SIGINT is sent to all processes in the process group of the foreground process. In this case, it means a SIGINT will be received by both the cat command and the bash process interpreting your script.

  • When you trap INT, an INT will no longer cause the process to exit unless you explicitly exit in your handler.

  • When you trap EXIT, your argument is run not on a particular signal but rather on the exit from the shell.

The behavior of trapping-int.sh is straightforward given these facts, since we know the following happens:

  • The cat process receives a SIGINT and its execution is terminated.
  • The bash process receives a SIGINT and runs its signal handler, printing "Exiting\n" to STDOUT.
  • The bash process continues execution, and prints "Hello\n" to STDOUT.
  • The bash process exits when it reaches the end of the script.

The behavior of trapping-exit.sh is mostly straightforward as well:

  • The cat process receives a SIGINT and its execution is terminated.
  • The bash process receives a SIGINT and since there is no signal handler it also, exits. It does /not/ run the echo command since it is exiting immediately upon receiving the signal.
  • Since the bash process is exiting, the EXIT handler runs, printing "Exiting\n" to STDOUT.

The remaining question is "where is the newline coming from?" I believe what is happening is that bash itself is installing a SIGINT handler that prints a newline.

In your trapping-int.sh script, you override Bash's handler for SIGINT, so you don't get the extra newline.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.