c - 重新注册信号处理程序会导致无限循环

标签 c signals posix infinite-loop sigint

使用以下信号处理程序,按 Ctrl-C导致处理程序被重复调用,我不知道为什么:

(警告:如果您输入 Ctrl-C ,则必须使用 kill <pid> 退出程序)

static void handler(int sig) {
        // do something interesting

        // write so I can see if I'm in an infinite loop
        write(1, "A", 1);

        // raise normal signal behavior
        // this ensures normal signal behavior
        // for example, exiting with code 130 if Ctrl-C is used
        signal(sig, SIG_DFL);
        raise(sig);

        // re-register handler
        // that way, if signal doesn't exit the program and the signal
        //   is sent again in the future, this handler will run again
        signal(sig, handler);
}

所以我知道我对信号处理程序不了解。我假设只有SIGCONT永远不会到达最后一行,因为 SIGINT (例如),当它以默认行为( SIG_DFL )引发时,应该退出而不返回。

我还知道我可以将最后一行包装在 if 语句中,该语句仅适用于 SIGCONT ,但我真的很想知道为什么它的行为不符合我的预期。

问题

  1. 为什么信号处理程序会在无限循环中被调用?
  2. 如何让处理程序执行一些有趣的操作、调用默认行为,然后在默认行为不退出程序的情况下重新注册自身?

MCVE

可以通过将其写入文件来运行 sigtest.c并在做make sigtest 。使用Ctrl-C筹集SIGINT ,并在另一个终端中准备执行 ps | grep sigtest然后kill <pid> .

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

static void handler(int sig) {
        // do something interesting

        // write so I can see if I'm in an infinite loop
        write(1, "A", 1);

        // raise normal signal behavior
        // this ensures normal signal behavior
        // for example, exiting with code 130 if Ctrl-C is used
        signal(sig, SIG_DFL);
        raise(sig);

        // re-register handler
        // that way, if signal doesn't exit the program and the signal
        //   is sent again in the future, this handler will run again
        signal(sig, handler);
}

int main(void) {
        char c;
        signal(SIGINT, handler);
        signal(SIGTSTP, handler);
        signal(SIGCONT, handler);
        printf("type 'x' and 'Enter' to exit\n");
        while (1) {
                c = getchar();
                printf("got char: %c\n", c);
                if (c == 'x') { break; }
        }
}

最佳答案

我一片空白,忘记了信号在处理时被阻止了。这意味着在处理程序返回之后以及我将操作从 SIG_DFL 设置回我的自定义之后,实际上不会引发 SIGINT处理程序。因此,它是循环的。

我的示例的工作处理程序如下所示:

static void handler(int sig) {
        if (sig == SIGCONT) {
                // do something interesting
                signal(sig, handler);
                signal(SIGTSTP, handler);
        } else {
                // do something else interesting
                signal(sig, SIG_DFL);
                raise(sig);
        }
}

关于c - 重新注册信号处理程序会导致无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48244907/

相关文章:

c - 用C读取txt文件的内容并遵循条件

c - 在同一台计算机上跨两个进程发送/处理信号的问题 - C 编程

c - posix线程内存消耗

c - 客户端异常终止如何通知服务器?

c - Posix 套接字 : Find out greatest number of file descriptors

在写入文件之前检查文件是否存在,然后要求用 POSIX 在 C 中覆盖

c - 了解 Linux 模块代码片段

c - 如何使用 Adaptive Simpsons 的维基百科代码来处理不同的功能

c - Arduino 使用 2-l298N 电机 Controller 通过蓝牙控制 4 个电机

c - ARM 平台上没有来自 SIGABRT 信号的回溯?