2016-04-14 4 views

答えて

2

シグナル・ハンドラはそうthread_localが有効な意味を持っていない、彼らは上で実行しているどのスレッドの概念を持っていません。 【intro.multithread] P2:

raise関数への呼び出しの結果として実行されるシグナルハンドラはraise関数への呼び出しとして実行の同じスレッドに属します。それ以外の場合は、どのスレッドに信号ハンドラ呼び出しが含まれているかは不明です。また

関連P23である:彼らは異なるスレッドによって実行される、または

  • 彼らはunsequencedあり、そして少なくとも一つされている

    • 場合

      つのアクションは、潜在的に同時ですシグナルハンドラによって実行されます。

    プログラムの実行は、シグナルハンドラのための特別な場合を除き、それはアトミックではない少なくとも1つのうち2つの潜在的に同時矛盾する行動を、含まれている場合データレースを含まず、どちらも他の前に起こります以下で説明します。そのようなデータ競合は、未定義の動作をもたらす。

    (シグナルハンドラのための特別な場合のみタイプvolatile sig_atomic_tに関するていると呼ばれている、ここでは適用されない。)

    第二弾が原因[intro.execution] P6の関係:

    raise関数の呼び出しの結果としてシグナルハンドラが実行された場合、ハンドラの実行はraise関数が呼び出された後で復帰する前にシーケンス化されます。 [注:信号が別の理由で受信されると、シグナルハンドラの実行は、通常、プログラムの残りの部分と並んでいません。 - エンドノート]

  • +0

    シグナルハンドラは[\ [support.runtime \]/10](http://eel.is/c++draft/support.runtime#10)によって制約されます。 –

    0

    この回答はildjarnによって与えられた答えに補遺考えることができます。 C++ 14標準について厳密に言えば、信号ハンドラからのthread_localストレージでデータを使用すると、未定義の動作が発生します。

    ただし、特定のプラットフォームでは、このような使用が許可されている可能性があります。たとえば、ほとんどのPOSIXシステムでは、スレッドごとに(スタックのように)割り当てられた特別なデータセグメントを使用してスレッドローカルストレージを実装しています。詳細な説明については、this documentを参照してください。この場合、スレッドローカルデータへのアクセスはロックを伴わないため、非同期信号安全です。

    ただし、アトミックがアクセスされていないか、またはアクセスがstd::atomic_signal_fenceを使用してフェンス化されていない限り、シグナルハンドラによって読み取られたり書き込まれたデータは、矛盾する可能性があります。この理由は、シグナルハンドラが実行を中断し、読み書き命令を並べ替える可能性があるときにコンパイラが考えているからです。 std::atomic_signal_fenceは、この並べ替えを禁止し、CPUによる並べ替えは同じスレッド内で実行され、結果(スレッド内の)が命令が順番に実行された場合と同じである場合にのみ命令の並べ替えを許可されるため、 。

    std :: atomic_signal_fenceに加えて、std :: atomic型の変数はロックされていない限り安全です(std :: is_lock_freeで示される)。

    Linuxでは(と私はほとんどのPOSIXプラットフォームを信じています)、シグナルが特定のスレッドにディスパッチされるかどうかは、このシグナルの生成方法とシグナルの正確なタイプによって決まります。たとえば、SIGSEGVSIGBUSは、エラーの原因となったスレッドに常に送出されます。この場合、スレッドローカルストレージを使用することは、そのようなエラーから回復するための便利な方法です。しかし、C++標準をサポートするすべてのプラットフォームにコードを移植可能にしながら、これを行う方法はありません。

    関連する問題