未处理的强制展开导致中止
因此,我对 pthread_exit 和 pthread_cancel 的理解是,它们都会导致称为“强制展开”的类似异常的事情被抛出目标中的相关堆栈帧线。可以捕获它以进行特定于线程的清理,但必须重新抛出,否则我们会在 catch 块末尾得到一个隐式的 abort() ,而该块不会重新抛出扔。
对于 pthread_cancel 来说,这种情况要么在收到关联信号时立即发生,要么在下一次进入取消点时发生,或者在信号下次解除阻塞时发生,具体取决于线程的取消状态和类型。
在pthread_exit
的情况下,调用线程立即进行强制展开。
美好的。这个“异常”是杀死线程过程中的正常部分。那么,为什么即使我重新抛出它,它也会导致 std::terminate()
被调用,从而中止我的整个应用程序?
请注意,我多次捕获并重新抛出异常。
另请注意,我正在从我的 SIGTERM
信号处理程序中调用 pthread_exit
。这在我的玩具测试代码中工作得很好,用 g++ 4.3.2 编译,它有一个线程运行 signal(SIGTERM, handler_that_calls_pthread_exit)
然后坐在一个紧密的 while
循环中,直到它收到 TERM
信号。但在实际应用中却行不通。
相关堆栈框架:
(gdb) where
#0 0x0000003425c30265 in raise () from /lib64/libc.so.6
#1 0x0000003425c31d10 in abort () from /lib64/libc.so.6
#2 0x00000000012b7740 in sv_bsd_terminate () at exception_handlers.cpp:38
#3 0x00002aef65983aa6 in __cxxabiv1::__terminate (handler=0x518)
at /view/ken_gcc_4.3/vobs/Compiler/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:43
#4 0x00002aef65983ad3 in std::terminate ()
at /view/ken_gcc_4.3/vobs/Compiler/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:53
#5 0x00002aef65983a5a in __cxxabiv1::__gxx_personality_v0 (
version=<value optimized out>, actions=<value optimized out>,
exception_class=<value optimized out>, ue_header=0x645bcd80,
context=0x645bb940)
at /view/ken_gcc_4.3/vobs/Compiler/gcc/libstdc++-v3/libsupc++/eh_personality.cc:657
#6 0x00002aef6524d68c in _Unwind_ForcedUnwind_Phase2 (exc=0x645bcd80,
context=0x645bb940)
at /view/ken_gcc_4.3/vobs/Compiler/gcc/libgcc/../gcc/unwind.inc:180
#7 0x00002aef6524d723 in _Unwind_ForcedUnwind (exc=0x645bcd80,
stop=<value optimized out>, stop_argument=0x645bc1a0)
at /view/ken_gcc_4.3/vobs/Compiler/gcc/libgcc/../gcc/unwind.inc:212
#8 0x000000342640cf80 in __pthread_unwind () from /lib64/libpthread.so.0
#9 0x00000034264077a5 in pthread_exit () from /lib64/libpthread.so.0
#10 0x0000000000f0d959 in threadHandleTerm (sig=<value optimized out>)
at osiThreadLauncherLinux.cpp:46
#11 <signal handler called>
谢谢!
埃里克
So my understanding of both pthread_exit
and pthread_cancel
is that they both cause an exception-like thing called a "forced unwind" to be thrown out of the relevant stack frame in the target thread. This can be caught in order to do thread-specific clean-up, but must be re-thrown or else we get an implicit abort()
at the end of the catch block that didn't re-throw.
In the case of pthread_cancel
, that happens either immediately on receipt of the associated signal, or the next entry into a cancellation point, or when the signal is next unblocked, depending on the thread's cancellation state and type.
In the case of pthread_exit
, the calling thread immediately undergoes a forced unwind.
Fine. This "exception" is a normal part of the process of killing a thread. So why, even when I re-throw it, is it causing std::terminate()
to be called, aborting my whole application?
Note that I'm catching and re-throwing the exception a couple times.
Note also that I'm calling pthread_exit
out of my SIGTERM
signal handler. This works fine in my toy test code, compiled with g++ 4.3.2, which has a thread run signal(SIGTERM, handler_that_calls_pthread_exit)
and then sit in a tight while
loop until it gets the TERM
signal. But it doesn't work in the real application.
Relevant stack frames:
(gdb) where
#0 0x0000003425c30265 in raise () from /lib64/libc.so.6
#1 0x0000003425c31d10 in abort () from /lib64/libc.so.6
#2 0x00000000012b7740 in sv_bsd_terminate () at exception_handlers.cpp:38
#3 0x00002aef65983aa6 in __cxxabiv1::__terminate (handler=0x518)
at /view/ken_gcc_4.3/vobs/Compiler/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:43
#4 0x00002aef65983ad3 in std::terminate ()
at /view/ken_gcc_4.3/vobs/Compiler/gcc/libstdc++-v3/libsupc++/eh_terminate.cc:53
#5 0x00002aef65983a5a in __cxxabiv1::__gxx_personality_v0 (
version=<value optimized out>, actions=<value optimized out>,
exception_class=<value optimized out>, ue_header=0x645bcd80,
context=0x645bb940)
at /view/ken_gcc_4.3/vobs/Compiler/gcc/libstdc++-v3/libsupc++/eh_personality.cc:657
#6 0x00002aef6524d68c in _Unwind_ForcedUnwind_Phase2 (exc=0x645bcd80,
context=0x645bb940)
at /view/ken_gcc_4.3/vobs/Compiler/gcc/libgcc/../gcc/unwind.inc:180
#7 0x00002aef6524d723 in _Unwind_ForcedUnwind (exc=0x645bcd80,
stop=<value optimized out>, stop_argument=0x645bc1a0)
at /view/ken_gcc_4.3/vobs/Compiler/gcc/libgcc/../gcc/unwind.inc:212
#8 0x000000342640cf80 in __pthread_unwind () from /lib64/libpthread.so.0
#9 0x00000034264077a5 in pthread_exit () from /lib64/libpthread.so.0
#10 0x0000000000f0d959 in threadHandleTerm (sig=<value optimized out>)
at osiThreadLauncherLinux.cpp:46
#11 <signal handler called>
Thanks!
Eric
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是你的问题。引用 POSIX 规范 (http://pubs.opengroup.org/onlinepubs/009695399/functions/signal.html):
允许的函数列表位于 http://pubs.opengroup.org/ onlinepubs/009695399/functions/xsh_chap02_04.html#tag_02_04_03,并且不包含
pthread_exit()
。因此,您的程序表现出未定义的行为。我可以想到三种选择:
pthread_cancel()
。This is your problem. To quote from the POSIX specs (http://pubs.opengroup.org/onlinepubs/009695399/functions/signal.html):
The list of permitted functions is given at http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html#tag_02_04_03, and does not include
pthread_exit()
. Therefore your program is exhibiting undefined behaviour.I can think of three choices:
sigwait()
to explicitly wait for the signal on an independent thread. This thread can then explicitly callpthread_cancel()
on the thread you wish to exit.sigpending()
periodically on the thread that is to be exited, and exit if the signal is pending.