3

POSIX では、スレッド キャンセル タイプとしてPTHREAD_CANCEL_ASYNCHRONOUS、およびPTHREAD_CANCEL_DEFERRED( によって設定されるpthread_setcanceltype(3)) いつpthread_cancel(3)有効になるかを決定する 2 つのタイプが指定されています。私の読んだところでは、POSIX のマニュアル ページではこれらについてあまり説明されていませんが、Linux のマニュアル ページでは次のように説明されていますPTHREAD_CANCEL_ASYNCHRONOUS

スレッドはいつでもキャンセルできます。(通常、キャンセル依頼を受け次第すぐにキャンセルとなりますが、システム上保証するものではありません。)

システムがこれを保証するものではないという意味が気になります。これがマルチコア/マルチ CPU システム (コンテキスト スイッチの前) で発生していることは容易に想像できます。しかし、シングル コア システムはどうでしょうか。

  1. pthread_setcancelstate(3)キャンセルが要求され、キャンセルが有効 ( ) で、キャンセル タイプが に設定されている場合、スレッドをすぐにキャンセルしないようにすることはできPTHREAD_CANCEL_ASYNCHRONOUSますか?
  2. はいの場合、これはどのような条件下で発生する可能性がありますか?

私は主に Linux (LinuxThreads / NPTL) に興味がありますが、より一般的には、このキャンセル ビジネスを POSIX 標準に準拠して表示する方法についても興味があります。

更新/明確化:ここでの実際の懸念事項はpthread_cancel()、ターゲット スレッドでキャンセルが有効になっており、型に設定されている呼び出しの直後に破棄されるリソースの使用ですPTHREAD_CANCEL_ASYNCHRONOUS!!! つまり、要点は次のとおりです。この場合、キャンセルされたスレッドが、コンテキストの切り替え後も (非常に短い時間でも) 正常に実行し続ける可能性はわずかにあるのでしょうか?

Damon の回答に感謝します。次のコンテキスト スイッチに関連するシグナルの配信と処理に関する質問が減りました。

Update-2:私は自分の質問に答えて、これは悪い懸念であり、根本的なプログラム設計は根本的に異なる概念レベルで対処する必要があることを指摘しました。この「間違った」質問が、非同期キャンセルの謎について疑問に思っている他の人にとって役立つことを願っています。

4

2 に答える 2

8

意味はまさにそれが言っていることです:それはすぐに起こるとは限りません. この理由は、実装の詳細に関する特定の「自由」が必要であり、標準で説明されているためです。

たとえば、Linux/NPTL では、キャンセルはシグナル nr を送信することによって実装されます。32. シグナルが受信されると、スレッドはキャンセルされます。これは通常、次のカーネルからユーザーへの切り替え時、次の割り込み時、またはタイム スライスの最後に発生します (偶然にすぐに発生する可能性がありますが、通常はそうではありません) 。 )。ただし、スレッドが実行されていない間はシグナルは受信されません。したがって、ここでの本当の問題は、シグナルが必ずしもすぐに受信されるとは限らないということです。

考えてみれば、それを大きく変えることさえできません。オペレーティング システムが実行しなければならないいくつかのハンドラーを実行できるため (スレッドを爆破して消滅させることはできません!)、キャンセルするにphtread_cleanup_pushはスレッドを必ず実行する必要があります。特定のスレッド (キャンセルしたいスレッドを含む) が、スレッドをキャンセルした正確な時間に実行されているという保証はありません。したがって、そのスレッドがすぐにキャンセルされるという保証はありません
もちろん、OS が呼び出し元のスレッドをブロックし、キャンセルされるスレッドをスケジュールするように実装されている場合を除いて、そのハンドラーを実行し、後で pthread_cancel のブロックを解除するだけです。しかしそれ以来pthread_cancelブロッキングとして指定されていない場合、これはまったく厄介な驚きです。また、実行時間の制限とスケジューラの公平性に干渉するため、多少受け入れられません。

したがって、キャンセルタイプが「無効」の場合、何も起こりません。または、「有効」で、キャンセル タイプが「延期」の場合、 にキャンセル ポイントとしてリストされている関数を呼び出すと、スレッドはキャンセルしpthreads(7)ます。
または、「非同期」である場合、上記のように、OS は、適切と見なされるとすぐにスレッドをキャンセルするために「何か」を実行します。正確で明確に定義された時間ではなく、「すぐに」です。Linux の場合は、シグナルを送信します。

于 2013-07-18T10:37:30.670 に答える
0

非同期キャンセルがいつ発生するかを知りたければ、何かひどく間違ったことをしているのです。

  1. 基準に従う:意図的にコードを作成したり、その正確性がプラットフォームに関する仮定 (単一コア、特定の実装など) に依存するコードを存在させたりすることで、自分の足元を食い尽くしています。可能であれば、ほとんどの場合、標準に従うことをお勧めします (それが不可能な場合は明確に文書化します)。名前自体は、即時またはほぼ即時とは異なる非同期PTHREAD_CANCEL_ASYNCHROUNOUSの意味を示唆しています。元のポスターはシングル コアを具体的に述べていますが、非決定論的な方法で壊れるコードの存在を許可する必要があるのはなぜですか?あなたのコードは、真の並列マシン (複数のコアまたは CPU) で実行されるように配置されており、即時性を保証することは事実上不可能です (これには、他のコアの実行を停止するか、コンテキスト スイッチまたは OS/ CPU は、型にはまらない希望をサポートするためにサポートするつもりはありません)。 非同期スレッド キャンセル モードは、スレッドの即時キャンセルを保証するものではありません。したがって、たとえそれが機能するとしても、この方法でそれらを使用することは非常に紛らわしいハックです.

  2. 非同期の安全性:非同期キャンセルのメカニズムが気になる場合は、問題のスレッド (独立性の欠如のため) が純粋に計算的ではないか、非同期キャンセル セーフな方法で記述されていないのではないかという疑いが生じます。

    pthread_cancel(3)POSIX は、 、pthread_setcancelstate(3)、およびの 3 つの関数のみを async-cancel safe として指定していますpthread_setcancelmode(3)- IEEE Std 1003.1, 2013 Edition, 2.9.5を参照してください。このキャンセル モードは、(純粋な計算以外の) ライブラリ関数を呼び出さない純粋な計算タスクにのみ適しています。スレッドがデフォルトの遅延キャンセル モードで実行するように設定されている場合、そのようなコードはキャンセル ポイントを提供しません。したがって、そのようなモードを定義する理論的根拠

    クリティカル セクションでのキャンセルを無効にすることで、async-cancel-safe コードを書くことができます。しかし、ライブラリの作成者 (POSIX ライブラリの実装者を含む) は一般的に、一般的な慣例に従い、複雑さを回避し、さらにはパフォーマンスのオーバーヘッドを回避するという理由で、非同期の安全性を気にするべきではありません。ライブラリの作成者は気にする必要がないため、特に明記されていない限り、非同期の安全性を期待するべきではありません。

    コードが非同期セーフではなく (たとえば、キャンセルを一時的に無効にしたり、キャンセル モードを変更したりせずに POSIX/標準 C ライブラリを含む他のライブラリを呼び出した場合)、非同期キャンセルが発生すると、リソース (メモリなど) がリークし、一貫性のない状態が残る可能性があります。ロックされたミューテックスは他のスレッドをデッドロックし、現在想像できる、または想像できない他の多くの問題を引き起こします。(C++ で作成している場合、POSIX スレッドのキャンセルと例外処理との密接な関係により、他の問題に対処する必要があるようです。)

于 2013-07-27T05:00:53.143 に答える