Home > Back-end >  How exactly signal handler will work if it receives another signal while processed?
How exactly signal handler will work if it receives another signal while processed?

Time:06-04

I tried to test what exactly happened in the signal handler.

int num = 0;

void    handler(int signum, siginfo_t *sip, void *ptr)
{
    sleep(1);
    num   ;
    write(1, "processs!\n", 10);
}

int main(void)
{
    int pid = getpid();
    struct sigaction    act1;

    printf("%d\n", pid);

    //act1.sa_flags = SA_NODEFER;
    act1.sa_sigaction = &handler;
    sigaction(SIGUSR1, &act1, NULL);
    sigaction(SIGUSR2, &act1, NULL);
    while (1)
    {
        sleep(1);
        printf("%d\n", num);
    };
}

and in other process, I send two signals consequently like this: kill(pid, SIGUSR1); kill(pid, SIGUSR1);

as I know, signal handler blocks the signal that invoked himself..... and blocked signal is processed after the handler ends. I expect the handler will be called twice and global variable num will be 2;

but it was called just once and num is 1.

then I tried to send two different signal like this: kill(pid, SIGUSR1); kill(pid, SIGUSR2);

as I know, SIGUSR2 will be processed during the handler is still in sleep, and this first handler will quit here, and num will not work. it will be processed just once in the handler called later.

but the handler was called twice and num was 2 in this trial....

It there any misunderstanding in my thought about signal handler? I was so confused.

CodePudding user response:

Here's your misconception:

and this first handler will quit here, and num will not work.

When one signal handler interrupts another, once the interrupting one finishes, the interrupted one resumes where it left off. It doesn't just end early.

By the way, lots of problems with your code:

  1. Since you're not using SA_SIGINFO, your handler should only take one parameter and should go in sa_handler instead of sa_sigaction.
  2. You're not initializing most fields of the struct sigaction, so really weird stuff could end up happening when you call sigaction on it.
  3. You're really restricted in what you're allowed to do from inside a signal handler; in particular, you're not allowed to access a global variable of type int. Change num to be a volatile sig_atomic_t.
  4. You should basically never use write outside of a loop, since partial writes are allowed to happen at basically any time.

As for why sending SIGUSR1 twice doesn't always run the handler twice, that's because non-real-time signals are allowed to coalesce, so if your second kill happens before the signal handler for the first one starts running, then the second one effectively won't do anything.

  • Related