Since the SIGINT is blocked while you call select, it is not delivered and select()
is not interrupted. If your handler just calls exit()
and you want this even while your code calls select, the best solution would be to leave the signal mask alone. If you, for some reason, don't want your normal handler to be called while you call select()
, you can use the pselect()
function.
Edit:
When is the signal delivered
If the signal is enabled (ie. not blocked) and the process is running, immediately.
If the signal is enabled and the process is sleeping in an interruptible sleep (that means state==S in top/ps output), the syscall is interrupted (eg. by returning EINTR to the caller) and the signal handler is executed.
If the signal is blocked, it waits is delivered as soon as it is unblocked. Syscalls are not interrupted by blocked signals.
In your example, this means the select()
is waiting for input; when input becomes available, it returns, signal handler gets enabled (in the second call to sigprocmask) and handler is called.
This is how it looks in strace:
Process 22393 attached - interrupt to quit
19:31:05.844940 select(1, [0], NULL, NULL, NULL) = 1 (in [0])
19:31:12.131431 rt_sigprocmask(SIG_UNBLOCK, [INT TERM], [INT TERM], 8) = 0
19:31:12.131560 --- SIGINT (Interrupt) @ 0 (0) ---
19:31:12.131730 fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
19:31:12.131871 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7ffb000
19:31:12.132027 write(1, "signal..."..., 9) = 9
19:31:12.132148 exit_group(1) = ?
Process 22393 detached
How to enable the signals
To have the signal handler enabled all the time, just remove the calls to sigprocmask()
from your code.