csignals

Why does only one SIGINT get queued while others are ignored during signal handling in C?


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


Solution

  • 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 SIGINTs in quick succession, you are likely observing


    Additional notes: