简体   繁体   English

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

[英]Segmentation fault in sigaction signal handler

In my below code, if I'm declaring old_act as a global variable then the program works fine. 在我的下面的代码中,如果我将old_act声明为全局变量,那么程序运行正常。 If declared inside main: 如果在main中声明:

  1. If SA_RESTART used, it works fine 如果使用SA_RESTART,它可以正常工作
  2. If SA_RESTART not used, it causes segmentation fault. 如果未使用SA_RESTART,则会导致分段错误。

Can someone please help me comprehend what is happening. 有人可以帮我理解发生的事情。

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;
}

From gdb it looks like some function call is happening at illegal location ,but not sure: 从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) 

Try resetting all members of act_h to zero before assigning it. 尝试在分配之前将act_h所有成员重置为零。 Most likely the sa_flags has some random value which is making the signal action to behave differently. 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;

}

You must use one sigemptyset() or sigfillset() to initialize a signal set. 您必须使用一个sigemptyset()sigfillset()来初始化信号集。 Or, in Your specific case: 或者,在您的具体情况中:

sigemptyset(&act_h.sa_mask);

In Your case, bare in mind that C does not have stuff like "default constructor" or something. 在你的情况下,请记住C没有像“默认构造函数”之类的东西。 So, the signal set and other automatic variables are not being initialized automagically and most likely contains garbage values. 因此,信号集和其他自动变量不会自动初始化,并且很可能包含垃圾值。

Also, be aware that bluntly memsetting to zeroes the structure in question is unreliable way of properly initializing an empty signal set. 此外,请注意,直接将所述结构设置为零是正确初始化空信号集的不可靠方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM