代码之家  ›  专栏  ›  技术社区  ›  cong

Linux内核何时将SIGSEGV的信号处理程序重置为SIG_DFL?

  •  1
  • cong  · 技术社区  · 7 年前

    如果我已经为 SIGSEGV

    int *a = NULL;
    *a = 1;
    

    将调用处理程序,但此信号处理程序仅调用一次。所以,我猜Linux内核会将信号处理程序重置为 SIG_DFL ,但是什么时候?我想知道细节,所以我检查了Linux内核源代码,但还没有找到线索。如果你知道详细情况,请告诉我代码。

    1 回复  |  直到 7 年前
        1
  •  3
  •   Petr Skocik    7 年前

    这取决于如何注册信号处理程序。 sigaction 而且没有 SA_RESETHAND SIG_DFL (尽管从信号处理程序返回以响应 SIGSEGV 由于分段故障而交付的是(UB)。 具有 萨乌手 signal ,则未指定是否重置处理程序(因此不要使用 signal() ).

    例子:

    #include <signal.h>
    #include <unistd.h>
    
    int volatile*a;
    void h(int Sig) { write(1,"h\n", 2); }
    int main()
    {
        //sigaction(SIGSEGV,&(struct sigaction){.sa_handler=h}, 0); //won't reset the handler, will likely loop
        sigaction(SIGSEGV,&(struct sigaction){.sa_handler=h,.sa_flags=SA_RESETHAND}, 0); //will reset the handler
        //signal(SIGSEGV,h); //may or may not reset the handler
        *a=1;
        return 0;
    }
    
        2
  •  1
  •   Monk    7 年前

    正如@PSkocik正确回答的那样,在正常情况下,内核不会费事将信号操作更改为默认值,除非用户已经安装了带有 SA_RESETHAND sigaction ,.

    SIGSEGV 违约。假设用户安装了信号处理器,然后在生成信号之前耗尽整个内存。在这种情况下,内核将无法创建帧来执行信号处理程序,因为没有剩余内存。在检测到这种情况后,内核将执行以下操作:

    1. 检查用户是否已为安装了处理程序 . 如果是,则将操作更改为“默认也取消阻止” 西格塞格夫
    2. 传送 西格塞格夫