Итак, я понимаю как pthread_exit
, так и pthread_cancel
, что они оба вызывают нечто подобное исключению, называемое «принудительной раскруткой», которое выбрасывается из соответствующего кадра стека в целевом потоке. Это может быть перехвачено, чтобы выполнить очистку, зависящую от потока, но должно быть выполнено повторно, иначе мы получим неявный abort()
в конце блока catch, который не был переброшен.
В случае pthread_cancel
это происходит либо сразу после получения связанного сигнала, либо при следующем входе в точку отмены, либо при следующей разблокировке сигнала, в зависимости от состояния и типа отмены потока.
В случае pthread_exit
вызывающий поток немедленно подвергается принудительной раскрутке.
Отлично. Это «исключение» - нормальная часть процесса уничтожения потока. Так почему, даже когда я повторно бросаю его, он вызывает вызов std::terminate()
, прерывая все мое приложение?
Обратите внимание, что я перехватываю и повторно генерирую исключение пару раз.
Также обратите внимание, что я вызываю pthread_exit
из своего SIGTERM
обработчика сигналов. Это отлично работает в моем тестовом коде игрушек, скомпилированном с помощью 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>
Спасибо!
Эрик