1

(この質問は、シグナルハンドラーのpthread_exitがセグメンテーション違反を引き起こすことにある程度関連している可能性があります)私はリードロック防止ライブラリを書いています。ここでは、グラフ処理を実行するチェックスレッドが常にあり、デッドロックがあるかどうかをチェックします。競合するスレッド。そのスレッドがシグナルをキャッチすると、所有しているすべてのミューテックスを解放して終了します。複数のリソースミューテックス(明らかに)と1つのクリティカルリージョンミューテックスがあり、リソースロックの取得、解放、およびグラフ計算を行うためのすべての呼び出しは、最初にこのロックを取得する必要があります。今、問題があります。2つの競合する(チェックスレッドを数えない)スレッドで、時々1つのスレッドが強制終了されると、プログラムはデッドロックします。gdbでは、デッドスレッドがクリティカルリージョンロックを所有しているが、解放されていないことを示しています。シグナルハンドラーにブレークポイントを追加してステップスルーした後、ロックはpthread_exit()の直前に(予想どおり)他の誰かに属しているように見えますが、所有権はpthread_exit()の後に魔法のようにこのスレッドに移動します

。クリティカルリージョンロックを取得しようとしたときに(別のリソースミューテックスが必要だったため)強制終了されるスレッドがpthread_mutex_lockでブロックされていた場合、シグナルが送信され、pthread_mutex_lockが中断されました。この呼び出しは信号プルーフではないので、何か奇妙なことが起こりましたか?シグナルハンドラーが戻ってきて、そのスレッドがロックを取得して終了したように?Idk ..どんな洞察も大歓迎です!

4

1 に答える 1

3

pthread_exitは非同期シグナルセーフではないため、シグナルハンドラから呼び出すことができる唯一の方法は、シグナルが非同期シグナルセーフでない機能を中断していないことを確認することです。

一般的な原則として、スレッドとの通信方法としてシグナルを使用することは、通常、非常に悪い考えです。スレッドセーフ(スレッド間の適切な同期)と単一スレッド内の再入可能性という、それ自体ではすでに十分に困難な2つの問題が混在することになります。

シグナルの目的がスレッドに終了を指示することだけである場合、より良いメカニズムがありますpthread_cancel。ただし、これを安全に使用するには、キャンセルされるスレッドは、適切なポイントでキャンセルハンドラーを設定するか、安全でない場合はキャンセルを一時的に無効にする必要があります(を使用pthread_setcancelstate)。また、それpthread_mutex_lockはキャンセルポイントではないことに注意してください。ミューテックスを取得するために待機しているブロックされたスレッドを中断する安全な方法はありません。したがって、このような中断可能性が必要な場合は、条件変数を使用したより複雑な同期設定が必要になるか(condvar待機はキャンセル可能)、代わりにセマフォを使用できます。ミューテックス。

編集:ミューテックスを待機しているスレッドを終了する方法が本当に必要な場合は、への呼び出しを、タイムアウトごとにpthread_mutex_lock呼び出しと終了フラグのチェックをループする独自の関数の呼び出しに置き換えることができます。pthread_mutex_timedlock

于 2012-12-03T17:22:59.747 に答える