5

したがって、両方についての私の理解は、どちらもpthread_exitpthread_cancel強制アンワインド」と呼ばれる例外のようなものがターゲットスレッドの関連するスタックフレームからスローされるということです。これは、スレッド固有のクリーンアップを行うためにキャッチできますが、再スローする必要がありますabort()。そうしないと、catch ブロックの最後で再スローされなかった暗黙のメッセージが取得されます。

の場合pthread_cancel、スレッドのキャンセル状態とタイプに応じて、関連付けられたシグナルを受信した直後、キャンセル ポイントへの次のエントリ、またはシグナルが次にブロック解除されたときに発生します。

の場合pthread_exit、呼び出し元のスレッドはただちに強制的にアンワインドされます。

罰金。この「例外」は、スレッドを強制終了するプロセスの通常の部分です。では、なぜ、再スローしstd::terminate()ても呼び出されて、アプリケーション全体が中止されるのでしょうか?

例外を数回キャッチして再スローしていることに注意してください。

pthread_exitまた、SIGTERMシグナル ハンドラから呼び出していることにも注意してください。これは、g++ 4.3.2 でコンパイルされた私のおもちゃのテスト コードで問題なく動作します。このコードは、スレッドを実行し、シグナルを受信するまでsignal(SIGTERM, handler_that_calls_pthread_exit)タイトなループにとどまります。しかし、実際のアプリケーションでは機能しません。whileTERM

関連するスタック フレーム:

(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>

ありがとう!

エリック

4

1 に答える 1

7

また、SIGTERM シグナル ハンドラから pthread_exit を呼び出していることにも注意してください。

これはあなたの問題です。POSIX 仕様 (http://pubs.opengroup.org/onlinepubs/009695399/functions/signal.html) から引用するには:

シグナルが、abort()、raise()、kill()、pthread_kill()、または sigqueue() の呼び出しの結果以外で発生した 場合、シグナル ハンドラーが静的ストレージ期間以外のオブジェクトを参照する場合、動作は未定義です。 volatile sig_atomic_t として宣言されたオブジェクトに値を代入するか、シグナル ハンドラがシグナルの概念にリストされている関数以外の標準ライブラリの関数を呼び出す場合。

許可されている関数のリストはhttp://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html#tag_02_04_03にあり、pthread_exit(). したがって、プログラムは未定義の動作を示しています。

次の 3 つの選択肢が考えられます。

  1. シグナル ハンドラから直接終了しようとするのではなく、スレッドによって定期的にチェックされるシグナル ハンドラにフラグを設定します。
  2. sigwait()独立したスレッドでシグナルを明示的に待機するために使用します。pthread_cancel()このスレッドは、終了したいスレッドを明示的に呼び出すことができます。
  3. シグナルをマスクし、sigpending()終了するスレッドで定期的に呼び出し、シグナルが保留中の場合は終了します。
于 2011-06-29T09:29:54.883 に答える