Search code examples
csignalsstandardsc11

Replacing the SIGUSR1 signal handler works differently in standards C11 and GNU11


I would like to override the behaviour of the SIGUSR1 signal handler. But I get different results using different C standards. If I use the C11 standard, my signal handler gets replaced with the default one after receiving this signal once. So if I send the signal SIGUSR1 to the process twice, then the second time, the default SIGUSR1 handler is called instead of mine. But in the GNU11 standard, mine is called every time. How can I get this behaviour using the C11 standard?

Here's my code:

#include <stdlib.h>
#include <stdio.h>
#include <signal.h>

void noop(int signo)
{
    (void) signo;
}

int main(int argc, char **argv)
{
    (void) argc; (void) argv;

    if (signal(SIGUSR1, noop) == SIG_ERR)
    {
        perror("Can't register handler for signal SIGUSR1");
        exit(EXIT_FAILURE);
    }

    while (1);
}

Compile this program with the C11 standard:

gcc signal.c -o signal_c11.out -std=c11 -O0 -Wall -Wextra -Wpedantic
./signal_c11.out

Or compile this program with the GNU11 standard:

gcc signal.c -o signal_gnu11.out -std=gnu11 -O0 -Wall -Wextra -Wpedantic
./signal_gnu11.out

In another terminal, do

kill -s SIGUSR1 <pid-of-above-process>
kill -s SIGUSR1 <pid-of-above-process>

Then, the process from the program signal_c11.out will terminate as per the default action of the SIGUSR1 signal; but the process from the program signal_gnu11.out will continue running, how I expect it to be.

How can I get the gnu11 behaviour using the c11 standard?


Solution

  • The behavior for signal() changes between System V and BSD semantics based on some feature test macro definitions (see Portability on that man page).

    The primary difference in this case is that System V signal() auto resets the handler when it is invoked, where BSD does not.

    Using sigaction() you can set the behavior you expect (not setting the SA_RESETHAND flag, possibly setting the SA_RESTART flag).

    As the signal() manpage says:

    The behavior of signal() varies across UNIX versions, and has also varied historically across different versions of Linux. Avoid its use: use sigaction(2) instead.