【问题标题】:Catching signal inside its own handler在自己的处理程序中捕获信号
【发布时间】:2011-01-26 00:05:49
【问题描述】:
#include<stdio.h>
#include<signal.h>

void handler(int signo)
{
    printf("Into handler\n");
    while(1);
}
int main()
{
    struct sigaction act;
    act.sa_handler = handler;
    act.sa_flags = 0;
    sigemptyset(& act.sa_mask);
    sigaction(SIGINT, &act, NULL);
    while(1);
    return 0;
}

捕获一次 KeyboardInterrupt 后,当我再次按“Ctrl+C”时,未处理 SIGINT... 我打算每次按“Ctrl+C”时打印“Into handler”

我想在“SIGINT handler()”本身中捕获 SIGINT..

【问题讨论】:

    标签: c unix posix signals sigint


    【解决方案1】:

    你可以用这样的东西代替 printf:

    const char *str = "Into handler\n";
    write(1, str, strlen(str));
    

    函数write(..) 可以安全地从信号处理程序中调用。 不要忘记包含unistd.h 标头以使用它。

    【讨论】:

    • 您可能更安全地提及stdout 而不是1,因为有多种方式可能会导致此数字发生变化。
    【解决方案2】:

    不过,您正在做的事情似乎是一个非常糟糕的主意,最好从处理程序中简单地设置一个标志并从它返回,然后从 main 进行打印。

    您需要在信号处理程序本身中设置SA_NODEFER 或以其他方式重新启用信号,否则信号会在调用处理程序之前被阻塞或切换回其默认行为。

    从信号处理程序调用printf 是未定义的行为。它可能会使您的程序崩溃。您实际上可以从信号处理程序安全调用的函数列表非常有限。 I need a list of Async-Signal-Safe Functions from glibc

    【讨论】:

    • “似乎是个非常糟糕的主意”+1。一般来说,保持信号处理程序尽可能简短和简单是可行的方法。
    • 这就是我写“sigemptyset(& act.sa_mask);”的原因所以没有信号被屏蔽..我错在哪里?
    • 实际上,我想学习“如何在自己的信号处理程序中捕获特定信号?”。这就是我问这个问题的原因
    • 在调用信号处理程序之前,信号被阻塞(或处理程序更改为 SIG_DFL)。您在此之前(主要)设置的内容无效。
    • 正如手册页中所说,这取决于实现。在 Linux 上,它只是在调用处理程序之前阻塞信号,并在处理程序返回后解除阻塞。
    【解决方案3】:

    在信号处理程序中使用printf 函数完全并不是一个好主意,因为它可能导致未定义的行为!代码示例缺少信号处理程序工作的重要部分......请查看我关于此here on 'Q6 的博客。如何捕获分段错误?'

    此外,您需要将while 循环替换为更强大的循环,以便在测试信号处理程序时退出程序......比如......你如何退出它?

    【讨论】:

    • 我刚刚开始阅读有关信号的内容...那么,正确的方法是什么?
    • 看代码,你会'sigemptyset',然后设置flags,'sigaction(SIGINT, &sigact, (struct sigaction *)NULL);'在它之后调用...它会捕获 SIGINT ..您在调用 'sigemptyset' 之前设置标志..顺便说一句,这在生产环境中使用并且在 AIX 下可以愉快地工作...
    【解决方案4】:

    您需要在 sa_mask 上设置 SA_NODEFER 以捕获与您当前正在处理的信号相同的信号:

    SA_NODEFER:不要阻止从它自己的信号处理程序中接收信号。 SA_NOMASK 是该标志的过时、非标准同义词。

    【讨论】:

    • 注意:这并不能保证您不会丢失信号!如果您的进程在不在时隙或不间断内核调用中时收到多个相同类型的非实时信号,那么第二个(以及更多)信号将丢失。
    【解决方案5】:

    处理程序中的“while(1)”正在阻止第一个服务调用返回。删除它,随后的中断应该会​​导致再次调用处理程序。

    中断服务程序不应阻止调用线程返回。

    【讨论】:

    • 然后重写你的 Unix 内核。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多