15

シグナル ハンドラー内では、非同期セーフ関数のみを呼び出す必要があると言われています。私の質問は、非同期安全性を構成するものは何ですか? 再入可能スレッドセーフな関数は非同期セーフだと思いますか? それともいいえ?

4

2 に答える 2

14

再入可能性とスレッド セーフは、これとほとんどまたはまったく関係がありません。これらの機能の副作用、状態、および中断は重要な事実です。

非同期セーフ関数[GNU Pth]

関数は、シグナル ハンドラー コンテキスト内から副作用なく安全に呼び出すことができる場合、非同期セーフまたは非同期シグナル セーフです。つまり、一貫性のない状態を引き起こすことなく、順不同で直線的に実行するには、いつでも中断できる必要があります。また、グローバル データ自体が不整合な状態にある可能性がある場合にも、適切に機能する必要があります。いくつかの非同期セーフ操作を次に示します。

  • 関数を呼び出してsignal()シグナル ハンドラを再インストールする
  • 無条件にvolatile sig_atomic_t変数を変更します (この型への変更はアトミックであるため)
  • 関数を呼び出して_Exit()プログラムの実行を即座に終了する
  • 実装で指定された非同期セーフ関数を呼び出す

移植可能な非同期セーフの関数はほとんどありません。関数が他の操作を実行する場合、その関数はおそらく移植性の高い非同期セーフではありません。

経験則は次のとおりです - シグナルハンドラーからいくつかの条件変数のみを通知します (futex/pthread 条件、epoll ループの起動など)。

アップデート:

EmployedRussianが示唆したように、電話でさえpthread_cond_signal悪い考えです。最近のソースコードを確認したところ、eglibcロック/ロック解除のペアが含まれています。したがって、デッドロックの可能性が生じます。これにより、他のスレッドに通知するためのいくつかのオプションが残ります。

  1. を使用しeventfdます。
  2. グローバル アトミック変数を変更し、SA_RESTART が設定されておらず、他のスレッドがアトミックをチェックすることを期待します。
于 2011-12-13T17:04:45.860 に答える
1

独自のコードの場合、はい、リエントラントとスレッドセーフが必要な特性です。信号処理メカニズムの設定方法によっては、信号ハンドラー自体が別の信号によって中断される可能性があるためです。一般に、シグナルハンドラー内で行う作業はできるだけ少なくするようにしてください。通常のプログラムフローで特別なコードをトリガーするようにフラグを設定するだけで、おそらく実行する必要があります。

呼び出す可能性のあるOSの関数についてman 7 signalは、安全に呼び出すことができる関数のリストを確認してください。malloc()free()はリストにないことに注意してください。pthread同期APIもリストに含まれていませんが、安全に呼び出すことができるAPIもあると思います。そのため、シグナルハンドラーでグローバルフラグを安全に設定できます。

于 2011-12-13T17:12:13.733 に答える