That's how bash behaves when its process group receives a SIGINT but the program currently running on the foreground terminates normally. Take these two for example:
$ bash -c 'sh -c "trap true INT; sleep 10"; echo reached'
^Creached
$
$ bash -c 'sleep 10; echo reached'
^C
echo
is reached in the first case because SIGINT is caught and handled by sh
(as otherwise it wouldn't be possible to run the trap set for it), and ignored by bash since it didn't interrupt sh
when it arrived.
In the second, sleep
is interrupted as it doesn't catch SIGINT. Bash discerns this (using WIFSIGNALED
and WTERMSIG
macros), resets the handler for SIGINT to default, and signals itself to stage a SIGINT-caused termination.
The rationale for this behavior is given here as follows:
The basic idea is that the user intends a keyboard-generated SIGINT to go
to the foreground process; that process gets to decide how to handle it;
and bash reacts accordingly. If the process dies to due SIGINT, bash acts
as if it received the SIGINT; if it does not, bash assumes the process
handled it and effectively ignores it.
Consider a process (emacs is the usual example) that uses SIGINT for its
own purposes as a normal part of operation. If you run that program in a
script, you don't want the shell aborting the script unexpectedly as a
result.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…