替换 SIGUSR1 信号处理程序在标准 C11 和 GNU11 中的工作方式不同

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

我想覆盖 SIGUSR1 信号处理程序的行为。但是我使用不同的 C 标准得到不同的结果。如果我使用 C11 标准,我的信号处理程序会在收到一次该信号后被默认的替换。因此,如果我向进程发送信号 SIGUSR1 两次,那么第二次将调用默认的 SIGUSR1 处理程序而不是我的。但在 GNU11 标准中,每次都会调用我的。如何使用 C11 标准获得此行为?

这是我的代码:

#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);
}

使用 C11 标准编译此程序:

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

或者用GNU11标准编译这个程序:

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

在另一个终端中,执行

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

然后,来自程序signal_c11.out的进程将按照SIGUSR1信号的默认动作终止;但是程序 signal_gnu11.out 的过程将继续 运行,我希望它是怎样的。

如何使用 c11 标准获得 gnu11 行为?

signal() 的行为根据某些功能测试宏定义在 System V 和 BSD 语义之间发生变化(请参阅该手册页上的可移植性)。

这种情况下的主要区别是 System V signal() 在调用时自动重置处理程序,而 BSD 不会。

使用 sigaction() 您可以设置您期望的行为(不设置 SA_RESETHAND 标志,可能设置 SA_RESTART 标志)。

signal() 联机帮助页所述:

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.

-D_DEFAULT_SOURCE 传递给 gcc。如果您没有启用严格的标准一致性(即没有 -std=c* 选项),则此标志是隐式定义的。

这会将所有与 C 库相关的内容从 gnu11 获取到 c11。但是,它不会获得任何语法内容,例如 typeof 或其他。