无法处理连续的SIGSEGV信号

时间:2014-03-24 14:30:30

标签: c fedora sigsegv

我正在尝试从我的代码处理SIGSEGV信号。我在Fedora 15下用C编写了以下代码。我的问题是没有为第二个分段错误调用信号处理程序。任何人都可以指出我做错了什么。

typedef struct _ST_DEMO
{
    int m_iUnused;

    _ST_DEMO()
    {
        m_iUnused = 0;
    }
} ST_DEMO;

jmp_buf ex_buf__;

static void sig_hdl (int sig, siginfo_t *siginfo, void *context)
{
    cout<<"Inside Signal Handler."<<endl;
    longjmp(ex_buf__, 1);
}

int main (int argc, char *argv[])
{
    ST_DEMO* pStDemo = 0;
    struct sigaction act;

    memset (&act, '\0', sizeof(act));

    /* Use the sa_sigaction field because the handles has two additional parameters */
    act.sa_sigaction = &sig_hdl;

    /* The SA_SIGINFO flag tells sigaction() to use the sa_sigaction field, not sa_handler. */
    act.sa_flags = SA_SIGINFO;

    if (sigaction(SIGSEGV, &act, NULL) < 0)
    {
        perror ("sigaction");
        return 1;
    }

    if(!setjmp(ex_buf__))
    {
        cout<<"Before First Seg Fault."<<endl;
        cout<<pStDemo->m_iUnused<<endl;
    }
    else
    {
        cout<<"After jump."<<endl;
    }

    cout<<"Before Second Seg Fault."<<endl;
    cout<<pStDemo->m_iUnused<<endl;

    while(1)
    {
        sleep(1);
    }

    return 0;
}

1 个答案:

答案 0 :(得分:2)

您的longjmp将导致您跳转到该位置,但您不会从信号处理程序返回。这意味着信号仍然被阻止(这是信号的默认行为,它们会被掩盖,直到您从信号处理程序返回)。

您可以通过在longjmp之前清除处理程序中的信号掩码来指示您希望再次发生信号来解决此问题。

  • 使用SA_NODEFER中的act.sa_flags标记,以防止它首先被屏蔽。
  • 使用siglongjmp / sigsetjmp功能,为您保存面具

或者

  • 在longjmp之前或之后调用sigprocmask以自行取消屏蔽。

警告:这是一件非常危险的事情(抓住SIGSEGV,然后从信号处理程序中取出longjmp),几乎不可能对它做任何有用的事情。

如果在任何非异步信号安全且可重入的功能中发生内存访问错误,则无论如何都无法以任何理智的方式继续。

但由于网站上有多个类似的问题,我猜这是一种练习。

相关问题: Catching Segmentation Violations and Getting on with Life

也很有用

Longjmp out of signal handler? longjmp() from signal handler