【问题标题】:Signal handling in linuxlinux中的信号处理
【发布时间】:2014-11-30 18:32:11
【问题描述】:

我试图了解信号处理的工作原理,因此我决定以另一种方式处理除零。程序应请求输入,直到不发生被零除。但是,我的处理程序在第一次跳转后被忽略,除法由系统处理。为什么会这样?

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

jmp_buf env;

void handler(int sig) {
    printf("Invalid input , try again\n");
    longjmp(env , 1);
}

int main() {
    signal(SIGFPE , handler);
    int x , y;
    setjmp(env);
    scanf("%d%d" , &x , &y);
    printf("%d\n" , x / y);
}

【问题讨论】:

  • 您的系统似乎正在使用 signal 的旧语义,一旦调用信号,就会将信号处理程序重置为 SIG_DFL。如果您只是阅读 signal(2)signal(7) 手册页,这种行为就不会让人感到意外,而使用 sigaction(2) 的解决方案也是如此。
  • @JoachimPileborg - 你应该把它变成一个答案。 TBF 到 OP,信号处理对于新手来说并不明显。
  • 阅读signal(7)this answer 来回答一个非常相似的问题。

标签: c linux signals


【解决方案1】:

您需要使用sigsetjmpsiglongjmp 而不是常规版本,因为常规版本无法正确恢复您的信号掩码。这是您的代码的工作版本:

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

jmp_buf env;

void handler(int sig) {
    printf("Invalid input , try again\n");
    siglongjmp(env , 1);
}

int main() {
    int x , y;

    signal(SIGFPE , handler);
    sigsetjmp(env, 1);
    scanf("%d%d" , &x , &y);
    printf("%d %d\n" , x, y);
    printf("%d\n" , x / y);
}

顺便说一句,我尝试按照 Joachim Pileborg 在 cmets 中的建议使用 sigaction,但这对我没有帮助。我认为这里的关键是,如果您只是简单地 longjmp 退出信号处理程序,则不会恢复信号上下文(这意味着 SIGFPE 可能会处于禁用状态)。

【讨论】:

  • 对。机器的行为在信号被阻塞时生成 SIGFPE is undefined,但 Linux 似乎将其视为信号未被阻塞并且处置为 SIG_DFL。
  • ... 也就是说,第一个 SIGFPE 进入处理程序,第二个(即使被 longjmp 意外阻塞)以核心终止。
猜你喜欢
  • 2011-01-28
  • 1970-01-01
  • 1970-01-01
  • 2014-04-29
  • 1970-01-01
  • 2021-05-19
  • 1970-01-01
  • 2013-07-30
  • 2012-07-25
相关资源
最近更新 更多