Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading 多线程进程在信号处理程序中退出时发生死锁_Multithreading_Pthreads_Signals_Deadlock_Signal Handling - Fatal编程技术网

Multithreading 多线程进程在信号处理程序中退出时发生死锁

Multithreading 多线程进程在信号处理程序中退出时发生死锁,multithreading,pthreads,signals,deadlock,signal-handling,Multithreading,Pthreads,Signals,Deadlock,Signal Handling,一个进程中有两个线程。当主线程接收到SEGV时,我使用信号处理程序使用pthread_kill向其他辅助线程发送一些内部信号,并使用此内部信号将辅助线程困在睡眠状态,以便我现在可以执行强制清理,并将跟踪转储从主线程堆栈到文件中,同时考虑到现在的单线程进程,(其他辅助线程处于休眠状态) 但,一旦我在主线程退出时遇到这个问题,进程就会离开(不退出)并且看起来很像 在两个线程之间以死锁状态存在 请帮助我为什么以及代码的哪个部分导致死锁 提前谢谢 Auxiliary Thread stack: Thr

一个进程中有两个线程。当主线程接收到SEGV时,我使用信号处理程序使用pthread_kill向其他辅助线程发送一些内部信号,并使用此内部信号将辅助线程困在睡眠状态,以便我现在可以执行强制清理,并将跟踪转储从主线程堆栈到文件中,同时考虑到现在的单线程进程,(其他辅助线程处于休眠状态)

但,一旦我在主线程退出时遇到这个问题,进程就会离开(不退出)并且看起来很像 在两个线程之间以死锁状态存在

请帮助我为什么以及代码的哪个部分导致死锁

提前谢谢

Auxiliary Thread stack:

Thread 2 (Thread 0x7fc565b5b700 (LWP 13831)):
#0  0x00007fc5668e81fd in nanosleep () from /lib64/libc.so.6
#1  0x00007fc566915214 in usleep () from /lib64/libc.so.6
#2  0x00000000009699a2 in SignalHandFun() at ...........
#3  <signal handler called>
#4  0x00007fc56691820a in mmap64 () from /lib64/libc.so.6
#5  0x00007fc5668a5bfc in _IO_file_doallocate_internal () from /lib64/libc.so.6
#6  0x00007fc5668b386c in _IO_doallocbuf_internal () from /lib64/libc.so.6
#7  0x00007fc5668b215b in _IO_new_file_underflow () from /lib64/libc.so.6
#8  0x00007fc5668b38ae in _IO_default_uflow_internal () from /lib64/libc.so.6
#9  0x00007fc566894bad in _IO_vfscanf_internal () from /lib64/libc.so.6
#10 0x00007fc5668a2cd8 in fscanf () from /lib64/libc.so.6
..... 
......
.....
#15 0x00007fc567259806 in start_thread () from /lib64/libpthread.so.0
#16 0x00007fc56691b64d in clone () from /lib64/libc.so.6
#17 0x0000000000000000 in ?? ()

Main Thread stack:

Thread 1 (Thread 0x7fc5679c0720 (LWP 13795)):
#0  0x00007fc56692878e in __lll_lock_wait_private () from /lib64/libc.so.6
#1  0x00007fc5668b504b in _L_lock_1309 () from /lib64/libc.so.6
#2  0x00007fc5668b3d9a in _IO_flush_all_lockp () from /lib64/libc.so.6
#3  0x00007fc5668b4181 in _IO_cleanup () from /lib64/libc.so.6
#4  0x00007fc566872630 in __run_exit_handlers () from /lib64/libc.so.6
#5  0x00007fc5668726b5 in exit () from /lib64/libc.so.6
#6  0x00000000009698e3 in SignalHandFun() at ....
#7  <signal handler called>
#8  0x000000b1000000b0 in ?? ()
#9  0x0000000000000000 in ?? ()
辅助线程堆栈:
螺纹2(螺纹0x7fc565b5b700(LWP 13831)):
#0 0x00007fc5668e81fd位于/lib64/libc.so.6的nanosleep()中
#1 0x00007fc566915214,位于/lib64/libc.so.6的usleep()中
#位于……….的SignalHandFun()中的2 0x00000000009699a2。。。。。。。。。。。
#3  
#来自/lib64/libc.so.6的mmap64()中的4 0x00007fc56691820a
#5 0x00007fc5668a5bfc位于/lib64/libc.so.6中的文件doallocate\u internal()中
#来自/lib64/libc.so.6的内部()中的0x00007fc5668b386c
#7 0x00007fc5668b215b位于/lib64/libc.so.6的新文件\u underflow()中
#8 0x00007fc5668b38ae位于/lib64/libc.so.6中的默认流内部()
#9 0x00007FC566894/lib64/libc.so.6中的vfscanf\u internal()中存在错误
#来自/lib64/libc.so.6的fscanf()中的10 0x00007fc5668a2cd8
..... 
......
.....
#15 0x00007fc567259806位于/lib64/libpthread.so.0的start_thread()中
#16 0x00007fc56691b64d位于/lib64/libc.so.6的克隆()中
#17 0x0000000000000000英寸()
主线程堆栈:
螺纹1(螺纹0x7fc5679c0720(LWP 13795)):
#0 0x00007fc56692878e位于/lib64/libc.so.6中的uu lll_lock_wait_private()中
#1 0x00007fc5668b504b位于/lib64/libc.so.6中的_L__锁_1309()中
#2 0x00007fc5668b3d9a位于/lib64/libc.so.6的所有锁()中
#3 0x00007fc5668b4181位于/lib64/libc.so.6的_IO_cleanup()中
#4 0x00007fc566872630在/lib64/libc.so.6中运行退出处理程序()
#5 0x00007fc5668726b5位于/lib64/libc.so.6的出口()中
#位于…的SignalHandFun()中的6 0x00000000009698e3。。。。
#7  
#8 0x000000b1000000b0英寸???()
#9 0x0000000000000000英寸???()

我假设您向另一个线程发送了一个信号,因为您想做一些异步信号安全函数无法完成的工作

问题是,如果您的信号处理程序在获取了任何锁的线程上被调用(例如在您的情况下,内部libio列表锁),则任何试图获取相同锁的线程都将无限期地阻塞:您无法从SIGSEGV处理程序返回,因此该锁将不再可用于锁定,等待该锁的线程也不会有任何进展。在您的情况下,
exit
函数需要获取libio列表锁,因为它必须通过打开所有打开文件流的列表并刷新它们,而打开新文件的线程在将新文件放入列表时获得锁

虽然这是一个实现细节,可以想象在未来的某个(远)点在glibc内部解决(我们最近所做的小改进对您的情况没有帮助),唯一的方法是在glibc中的最终进程退出过程之前调用
\u exit
,在您需要执行的清理之后。在您的情况下,可以从尽早注册的
atexit
处理程序执行此操作,但这取决于您的应用程序

关于崩溃处理程序,我们在此处发布了一些建议:


本文的重点是
fork
,但死锁问题在您的案例中几乎相同。

感谢Weimer的详细解释。