忽略 C 上的信号

Ignoring a signal on C

这不是代码问题,而是理论问题。

我之前有过这段代码:

void handler(int signal){
    printf("Handler called\n");
}

struct sigaction act;
act.sa_handler = &handler;
act.sa_flags = 0;


if (sigaction(SIGINT, &act, NULL) < 0){
    exit(1);
}

if (sigaction(SIGQUIT, &act, NULL) < 0){
    exit(1);
}

当我按下 ctrl + C 时,正在调用处理程序,但程序仍然退出。

现在,出于好奇,我尝试将标志更改为 SA_RESTART。现在不退出了。

为什么?

SA_RESTART 导致 EINTR 可中断系统调用(例如,read)在传递已处理信号后重新启动。

所以如果你有:

#include <unistd.h>
#include <signal.h>
#include <errno.h>

void handler(int signal)
{
    printf("Handler called\n");
}

int main()
{
    struct sigaction act;
    act.sa_handler = &handler;
    act.sa_flags = 0;
    if (sigaction(SIGINT, &act, NULL) < 0){ exit(1); }
    char ch; ssize_t nr;
    nr=read(0,&ch,1);
}

然后使用 SA_RESTART 就好像 nr=read(0,&ch,1); 行已被替换为

while(0>(nr=read(0,&ch,1)) && errno==EINTR){}`

请注意,您应该只调用信号处理程序中的异步信号安全函数。处理程序中的 printf 通常是未定义行为的秘诀,但在这种特殊情况下,您只中断本身是异步信号安全的代码 (read),这是相当安全的,尽管POSIX 没有明确批准它 (AFAIK)。