【问题标题】:Cannot handle consecutive SIGSEGV signal无法处理连续的 SIGSEGV 信号
【发布时间】:2014-05-01 23:32:54
【问题描述】:

我正在尝试处理来自我的代码的 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;
}

【问题讨论】:

    标签: c fedora segmentation-fault


    【解决方案1】:

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

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

    • 首先使用act.sa_flags 中的SA_NODEFER 标志来防止它被屏蔽。
    • 使用siglongjmp/sigsetjmp 函数,为您保存掩码

    或者

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

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

    如果内存访问错误发生在任何非异步信号安全和可重入的函数中,您将无法以任何理智的方式继续。

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

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

    也有用

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

    【讨论】:

    • 非常感谢您的回复。 SA_NODEFER 标志有效。顺便说一句,这不是练习。我正在使用第三方库从我的软件访问数据库。如果数据库以某种方式脱机,此库将崩溃。我只是试图处理 SIGSEGV 信号以阻止我的代码被核心转储。但是根据您的建议,如果即使在处理完信号后我也无法做任何理智的事情,那么我必须考虑其他事情。再次感谢。
    • 啊,是的,从 sigsegv 中恢复非常非常困难。对于这类问题,我通常会创建一个辅助进程来处理实际的数据库流量,并使用 IPC 进行通信。这是否是极端的矫枉过正取决于你。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 2015-03-11
    • 1970-01-01
    • 2014-07-21
    相关资源
    最近更新 更多