sigaction信号处理程序中的分段错误

时间:2013-09-04 06:02:04

标签: c linux gdb segmentation-fault signals

在我的下面的代码中,如果我将old_act声明为全局变量,那么程序运行正常。如果在main中声明:

  1. 如果使用SA_RESTART,则可以正常使用
  2. 如果未使用SA_RESTART,则会导致分段错误。
  3. 有人可以帮助我理解发生的事情。

    void sighandler(int signum)
    {
            printf("Caught signal:%d pressed ctrl+c!!\n",signum);
    }
    
    int main()
    {
            struct sigaction act_h;
            struct sigaction old_act;
            act_h.sa_handler = sighandler;
    //      act_h.sa_flags = SA_RESTART;
    
           sigaction(SIGINT,&act_h,&old_act);
    
            printf("This is an infinite loop\n");
            int remain=sleep(10);
            printf("remaining time in sec : %d\n",remain);
            printf("Before second sleep\n");
            sleep(10);
            printf("This is an infinite loop\n");
            return 0;
    }
    

    从gdb看起来,某些函数调用发生在非法位置,但不确定:

    This GDB was configured as "i686-linux-gnu".
    For bug reporting instructions, please see:
    <http://www.gnu.org/software/gdb/bugs/>...
    Reading symbols from /home/diwakar/Documents/my_C_codes/L2IT/SigHandling/a.out...done.
    [New LWP 5661]
    
    warning: Can't read pathname for load map: Input/output error.
    Core was generated by `./a.out'.
    Program terminated with signal 11, Segmentation fault.
    #0  0xb77c1938 in ?? ()
    (gdb) 
    
    
    (gdb) bt
    #0  0xb77c1938 in ?? ()
    Cannot access memory at address 0xe
    
    
    (gdb) run
    Starting program: /home/diwakar/Documents/my_C_codes/L2IT/SigHandling/a.out 
    This is an infinite loop
    ^C
    Program received signal SIGINT, Interrupt.
    0xb7fdd424 in __kernel_vsyscall ()
    (gdb) bt
    #0  0xb7fdd424 in __kernel_vsyscall ()
    #1  0xb7ed2f00 in nanosleep () from /lib/i386-linux-gnu/libc.so.6
    #2  0xb7ed2d1f in sleep () from /lib/i386-linux-gnu/libc.so.6
    #3  0x08048502 in main () at signal.c:33
    (gdb) disassemble
    Dump of assembler code for function __kernel_vsyscall:
       0xb7fdd414 <+0>: push   %ecx
       0xb7fdd415 <+1>: push   %edx
       0xb7fdd416 <+2>: push   %ebp
       0xb7fdd417 <+3>: mov    %esp,%ebp
       0xb7fdd419 <+5>: sysenter 
       0xb7fdd41b <+7>: nop
       0xb7fdd41c <+8>: nop
       0xb7fdd41d <+9>: nop
       0xb7fdd41e <+10>:    nop
       0xb7fdd41f <+11>:    nop
       0xb7fdd420 <+12>:    nop
       0xb7fdd421 <+13>:    nop
       0xb7fdd422 <+14>:    int    $0x80
    => 0xb7fdd424 <+16>:    pop    %ebp
       0xb7fdd425 <+17>:    pop    %edx
       0xb7fdd426 <+18>:    pop    %ecx
       0xb7fdd427 <+19>:    ret    
    End of assembler dump.
    (gdb) 
    

2 个答案:

答案 0 :(得分:6)

尝试在分配之前将act_h的所有成员重置为零。很可能sa_flags具有一些随机值,这使得信号操作表现得不同。

int main()
{
        struct sigaction act_h;
        struct sigaction old_act;

        //reset all members
        memset(&act_h, 0, sizeof(act_h));
        act_h.sa_handler = sighandler;
        .... //continue your code;

}

答案 1 :(得分:1)

您必须使用一个sigemptyset()sigfillset()来初始化信号集。或者,在您的具体情况中:

sigemptyset(&act_h.sa_mask);

在你的情况下,请记住C没有像“默认构造函数”之类的东西。因此,信号集和其他自动变量不会自动初始化,很可能包含垃圾值。

另外,请注意,直接将所讨论的结构设置为零是正确初始化空信号集的不可靠方法。