According to this detailed explanation of SIGINT handling, a process can't just catch SIGINT and exit because (1) the front-most process might intercept and inhibit the signal and (2) a process cannot communicate SIGINT to its caller via exit(). Instead, a caller should only process SIGINT after its children have exited for SIGINT, if they choose to exit, and the process should exit on SIGINT by sending SIGINT to itself and not catching it on the second round.
The same issues apparently apply to SIGQUIT.
To correct the problem, the handler should only conditionally process SIGINT when it has no child processes, and it will have to uninstall itself before sending a SIGINT to itself to finally exit.
@Banjocat on Stackoverflow points out that the SIGINT processing is all wrong.
According to this detailed explanation of SIGINT handling, a process can't just catch SIGINT and exit because (1) the front-most process might intercept and inhibit the signal and (2) a process cannot communicate SIGINT to its caller via
exit()
. Instead, a caller should only process SIGINT after its children have exited for SIGINT, if they choose to exit, and the process should exit on SIGINT by sending SIGINT to itself and not catching it on the second round.The same issues apparently apply to SIGQUIT.
To correct the problem, the handler should only conditionally process SIGINT when it has no child processes, and it will have to uninstall itself before sending a SIGINT to itself to finally exit.