Why does Bash ignore SIGINT if its currently running child handles it?

The problem is well explained here, as WCE wait and cooperative exit and I encourage you to read it. Basically, your signal is received by all foreground processes, ie the shell and the program, sleep or aplay. The program exits with return code 130 if it does not handle the signal. The shell does a wait for the child to end, and sees this, and the fact that it got the signal too, so exits.

When the program captures the signal, it often just exits with code 1 (as with aplay). When the shell waits for the child, it sees that it did not end due to the signal and so has to assume the signal was a normal aspect of the program's working, so the shell carries on as normal.

For your example, the best way to handle aplay is to check its return code for non-zero and stop:

(while aplay test.wav; do :; done)

The above-mentioned article goes on to explain that a well-behaved program that wants to trap sigint to do some cleanup, should then disable its handler, and re-kill itself in order to get the correct exit flags set.

Tags:

Bash

Signals