linux 捕获信号处理中遇到的死锁
2013-10-10 21:14
453 查看
tag: 信号 signal sigchld 死锁 堆栈
我们的程序需要捕获信号自己处理,所以尝试对1-32的信号处理(后面33-64的信号不处理)。
但是在调试代码时,发现一个线程死锁的问题。
程序目的:捕获信号,然后打印堆栈。
Thread 12 (Thread 0xf7dd2b90 (LWP 5770)):
以下是一个让我觉得奇怪的堆栈,奇怪之处:
1.死锁了:__lll_lock_wait_private
2.获得了2个信号:<signal handler called>,为什么不是一个一个信号处理
堆栈如下:
#18 0x0804fa02 in boom ()
boom()是我写的一个制造崩溃的函数:
char *pBoom = NULL;
memcpy( pBoom, "aaaa", 100 );
#16 <signal handler called>
触发信号
#15 0x080f9844 in TsSigHandler(int, siginfo*, void*) ()
TsSigHandler是信号处理函数。通过以下代码设置:
struct sigaction sigact;
sigemptyset( &sigact.sa_mask );
sigact.sa_flags = SA_ONESHOT | SA_SIGINFO;
sigact.sa_sigaction = TsSigHandler;
信号触发后,由TsSigHandler函数处理
#14 0x080f95c1 in PrintStack() ()
TsSigHandler函数中调用PrintStack函数打印堆栈。
#13 0x00317ead in system () from /lib/libpthread.so.0
PrintStack函数中调用了system函数做一些额外的事情,例如执行gcore(事实证明,这种方法是有点问题的)。
#11 0x001f8132 in do_system () from /lib/libc.so.6
system调用了do_system
#10 0x001eb1a9 in sigprocmask () from /lib/libc.so.6
do_system调用sigprocmask
#8 <signal handler called>
关键来了:这是获取到了另外一个信号:SIGCHLD。
#7 0x080f9844 in TsSigHandler(int, siginfo*, void*) ()
又调用信号处理函数TsSigHandler
#3 0x001f7f8b in do_system () from /lib/libc.so.6
system调用do_system,调用流程和上面当然是一样的
#2 0x001f8448 in _L_lock_124 () from /lib/libc.so.6
#1 0x002a0783 in __lll_lock_wait_private () from /lib/libc.so.6
nice!锁住了。。
分析:
system()函数执行的大体过程是:fork()->exec()->waitpid(),
waitpid用于等待子进程执行完毕。
但是在子进程执行完毕时,会产生SIGCHLD信号,
而SIGCHLD信号会唤醒wait中的进程,这就是看到了2个信号的原因,
解决方法:
1.忽略SIGCHLD信号:其实这个信号一般情况下应该被忽略,除非你的程序需要对这种情况做非常特殊的处理
2.不要在这里调用system()
to do: 有空了记得补详细些
我们的程序需要捕获信号自己处理,所以尝试对1-32的信号处理(后面33-64的信号不处理)。
但是在调试代码时,发现一个线程死锁的问题。
程序目的:捕获信号,然后打印堆栈。
以下是一个让我觉得奇怪的堆栈,奇怪之处:
1.死锁了:__lll_lock_wait_private
2.获得了2个信号:<signal handler called>,为什么不是一个一个信号处理
堆栈如下:
boom()是我写的一个制造崩溃的函数:
char *pBoom = NULL;
memcpy( pBoom, "aaaa", 100 );
#16 <signal handler called>
触发信号
#15 0x080f9844 in TsSigHandler(int, siginfo*, void*) ()
TsSigHandler是信号处理函数。通过以下代码设置:
struct sigaction sigact;
sigemptyset( &sigact.sa_mask );
sigact.sa_flags = SA_ONESHOT | SA_SIGINFO;
sigact.sa_sigaction = TsSigHandler;
信号触发后,由TsSigHandler函数处理
#14 0x080f95c1 in PrintStack() ()
TsSigHandler函数中调用PrintStack函数打印堆栈。
#13 0x00317ead in system () from /lib/libpthread.so.0
PrintStack函数中调用了system函数做一些额外的事情,例如执行gcore(事实证明,这种方法是有点问题的)。
#11 0x001f8132 in do_system () from /lib/libc.so.6
system调用了do_system
#10 0x001eb1a9 in sigprocmask () from /lib/libc.so.6
do_system调用sigprocmask
#8 <signal handler called>
关键来了:这是获取到了另外一个信号:SIGCHLD。
#7 0x080f9844 in TsSigHandler(int, siginfo*, void*) ()
又调用信号处理函数TsSigHandler
#3 0x001f7f8b in do_system () from /lib/libc.so.6
system调用do_system,调用流程和上面当然是一样的
#2 0x001f8448 in _L_lock_124 () from /lib/libc.so.6
#1 0x002a0783 in __lll_lock_wait_private () from /lib/libc.so.6
nice!锁住了。。
分析:
waitpid用于等待子进程执行完毕。
但是在子进程执行完毕时,会产生SIGCHLD信号,
而SIGCHLD信号会唤醒wait中的进程,这就是看到了2个信号的原因,
解决方法:
1.忽略SIGCHLD信号:其实这个信号一般情况下应该被忽略,除非你的程序需要对这种情况做非常特殊的处理
2.不要在这里调用system()
to do: 有空了记得补详细些
相关文章推荐
- Linux程序退出时的信号捕获及处理
- Linux开发调试经验整理(二)——信号处理函数陷阱:调用malloc导致死锁
- Linux开发调试经验整理(二)——信号处理函数陷阱:调用malloc导致死锁
- Linux信号来源和捕获处理以及signal函数简介
- [linux]信号的捕获和处理
- Linux C++ 处理 Kill 信号、Ctrl+C信号,便于安全退出
- linux下的僵尸进程处理SIGCHLD信号
- Linux Signal handling(信号处理)Arm64
- Linux 多线程应用中如何编写安全的信号处理函数
- 【拔苗计划】linux学习笔记——信号处理机制及kill、du、df命令
- 关于 Linux 中 signal 函数信号处理的讨论
- Linux 进程间通信--信号、TCP粘包处理
- Linux信号、信号处理和信号处理函数
- Linux下C语言编程--信号处理函数
- 我使用过的Linux命令之trap - 在脚本中处理信号
- Linux信号捕捉及其处理
- linux 异步信号的同步处理方式
- Linux信号机制与信号处理
- Linux进程间通信三之信号与处理
- Linux命令之trap - 在脚本中处理信号