【问题标题】:problems with sig handling of SIGSEGVSIGSEGV 的 sig 处理问题
【发布时间】:2012-03-27 22:14:39
【问题描述】:

我创建了一个信号处理程序,以便在发送 SIGSEGV 时调用。我正在使用 C 编写程序,还使用 ​​Linux 和 intel x86 处理器。在 sig 处理程序中,看起来通过 siginfo_t 结构传入的 si_addr 被赋予值 0 而不是导致问题的指令地址的值。我在 sigaction 中设置了 SIG_INFO 标志,所以我知道为什么会这样。

下面是一些示例代码:

int main(){
    mprotect(..., PROC_READ | PROC_WRITE /* | PROC_EXEC */);  //cannot execute page

    someMethodOnRestrictedPage();
    //do some stuff
}

void init_sighandler(void) {

    //initialize the sigaction so that sig handler is called when a SIGSEGV is thrown
    struct sigaction * action;

    action = (struct sigaction *) malloc(sizeof(struct sigaction));

    action->sa_sigaction = sighandler;
    sigemptyset (&action->sa_mask);

    action->sa_flags = 0;

    sigaddset(&action->sa_mask, SA_SIGINFO);
    sigaddset(&action->sa_mask, SA_RESTART);

    sigaction(SIGSEGV, action, NULL);
}

void sighandler(int sig, siginfo_t *siginfo, void *ucp){
    printf("%x\n", siginfo->si_addr);   // prints out 0
}

【问题讨论】:

  • 我很好奇:您为什么要尝试处理分段错误?你打算在你的处理程序中做什么?
  • 我正在限制对某些内存页面的访问,以便它故意创建一个 SIGSEGV,然后我正在处理它
  • 了解您在哪个平台上可能会有所帮助,以及您是否可以发布一个很棒的最小测试程序。
  • 执行 sighandler 时 siginfo 中还有什么?

标签: c segmentation-fault


【解决方案1】:

您的.sa_flags 已清除SA_SIGINFO 位。

引用http://pubs.opengroup.org/onlinepubs/7908799/xsh/sigaction.html

SA_SIGINFO

如果清零并捕捉到信号,则进入信号捕捉函数为:

void func(int signo);

其中signo 是信号捕获函数的唯一参数。在这种情况下必须使用sa_handler 成员来描述信号捕获功能,并且应用程序不得修改sa_sigaction 成员。

如果设置了SA_SIGINFO并捕捉到信号,则信号捕捉函数输入为:

void func(int signo, siginfo_t *info, void *context);

其中两个额外的参数被传递给信号捕获函数。第二个参数将指向siginfo_t 类型的对象,解释信号产生的原因;第三个参数可以转换为指向ucontext_t 类型对象的指针,以引用在传递信号时被中断的接收进程的上下文。在这种情况下必须使用sa_sigaction 成员来描述信号捕获功能,并且应用程序不得修改sa_handler 成员。

si_signo 成员包含系统生成的信号编号。

si_errno 成员可能包含依赖于实现的附加错误信息;如果非零,则它包含一个错误号,用于标识导致生成信号的条件。

si_code 成员包含识别信号原因的代码。如果si_code的值小于等于0,那么信号是由进程产生的,si_pidsi_uid分别表示进程ID和发送者的真实用户ID。 <signal.h> 标头描述包含有关siginfo_t 类型元素的信号特定内容的信息。

--结束引用

所以 sigaction 使用 .sa_handler 如果该位被清除,而.sa_sigaction 如果该位被设置。

所以你有未定义的行为,因为你正在阅读不成文的论点。

设置.sa_flags = SA_SIGINFO | ... 解决问题。

【讨论】:

  • 好的,谢谢!我以为我需要的只是 sigadset(&action->sa_mask, SA_SIGINFO);设置它,但我猜不是。
猜你喜欢
  • 2021-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-11
  • 2020-08-23
  • 1970-01-01
相关资源
最近更新 更多