I'm testing Unix signal behavior in C and noticed something odd. When I press Ctrl+C (sending SIGINT) multiple times quickly while the handler is still running (it sleeps for 3 seconds), only two handler calls happen — the first one immediately, and a second one after the first finishes. I sent the signal four times, so why does only one extra signal get handled while the others are ignored? I thought standard signals don’t queue, so shouldn’t all additional ones be skipped? Can someone explain the rules for how Unix handles this kind of signal queuing?
And yes i did use chatgpt to write the question, because English is not good enough.
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
int x = 0;
void signal_handler(int signum) {
printf("start\n");
sleep(3);
printf("end\n");
}
int main() {
signal(SIGINT, signal_handler);
while (1);
return 0;
}
in terminal:
^Cstart
^C^C^C^C^C^C^Cend
start
end
I'm testing Unix signal behavior in C and noticed something odd. When I press Ctrl+C (sending SIGINT) multiple times quickly while the handler is still running (it sleeps for 3 seconds), only two handler calls happen — the first one immediately, and a second one after the first finishes.
The only thing odd about that is that your signal handler sleeps.
I sent the signal four times, so why does only one extra signal get handled while the others are ignored?
C does not itself say, one way or the other, but conventionally, ordinary signals such as SIGINT
do not queue. Only one of each kind can be pending at a time, and additional ones that arrive while there is already one of the same kind pending are discarded.
But, at least in Unix, a signal with a handler registered is considered delivered (so no longer pending) as soon as the handler is called for it. Another signal of the same kind can therefore become pending right away, even before the handler returns. What happens then depends on the system and on details of how the handler was registered, but one common default is that a signal is blocked from being delivered while a handler function for that kind of signal is running.
I thought standard signals don’t queue, so shouldn’t all additional ones be skipped?
Multiple copies of the same standard signal don't queue, but signal delivery is asynchronous, and signals can be temporarily blocked, so there has to be some mechanism for retention of (at least) one signal of each kind.
When you use the keyboard to send multiple SIGINT
s in quick succession, you are likely observing
SIGINT
be dispatched to the handler before the second arrives,SIGINT
very soon after it is unblocked by completion of the previous handler call.Additional notes:
sigaction()
, not signal()
to register signal handlers.printf()
, are not async-signal-safe.