Search code examples
csignalssigactionsigqueue

Ignoring signal if it's sent too quickly


I have the following code:

//includes...

#define SIG_INT 0

//prints out <Text> when SIG_INT is received from siginfo_t*
void handler(int, siginfo_t*, void*);

int main()
{
    pid_t ambulance1 = 0;
    pid_t ambulance2 = 0;

    struct sigaction sigact;
    sigact.sa_sigaction = handler;
    sigemptyset(&sigact.sa_mask);
    sigact.sa_flags = SA_SIGINFO;
    sigaction(SIGUSR1, &sigact, NULL);

    ambulance1 = fork();
    if(ambulance1 > 0) {
        ambulance2 = fork();
        if(ambulance2 > 0) { // parent
            int status;
            waitpid(ambulance1, &status, 0);
            waitpid(ambulance2, &status, 0);

            printf("HQ went home!\n");
        }
    }

    if(ambulance1 == 0 || ambulance2 == 0) {
        union sigval signalValueInt;
        signalValueInt.sival_int = SIG_INT;

        sigqueue(getppid(), SIGUSR1, signalValueInt);

        printf("Ambulance[%d] ended.\n", getpid());
    }

    return 0;
}

What happens is: sometimes the second ambulance's sigqueue(getppid(), SIGUSR1, signalValueInt); doesn't get received, and the output is something like the following:

  1. Ambulance[20050] ended. // main() prints out this
  2. Ambulance[20051] ended. // main() prints out this
  3. // handler() prints out this with write() ONLY ONCE!
  4. HQ went home! // main() prints out this

I know that the signal is lost, because the two signals arrived too quickly after one another, and the operating sys. thinks it's an error-duplicate, so it gets ignored.

My question is:

Is there a way to tell the operating system not to do that?

I wouldn't like to use two different signals (ex.: SIGUSR1 and SIGUSR2) for the same purpose, and I also wouldn't like to use delay in one of the child process.


Solution

  • The answer is in the manual page of signal(7). But breafly: if a standard signal arrives (like SIGUSR1) while the handler is running it will get ignored by the operating system. if a real-time signal arrives (like SIGRTMIN) while handler is running it will be processed after the handler is done running.