web-dev-qa-db-ja.com

シグナルは無視できますか(失われますか)?

シグナルを介してワーカーと通信するアプリケーションがあります(特定のSIGUSR1/SIGUSR2/SIGSTOP)。

すべての信号がハンドラーによって配信および処理されることを信頼できますか?

アプリケーションが信号を処理できない場合よりも速く信号が送信された場合(たとえば、現時点でのホストの負荷が高いため)、どうなりますか?

9
KaP

「信号が多すぎる」問題は別として、信号は明示的に無視できます。から _man 2 signal_

_If the signal signum is delivered to the process, then one of the
following happens:    
  *  If the disposition is set to SIG_IGN, then the signal is ignored.
_

信号をブロックすることもできます。から _man 7 signal_ ;

_A signal may be blocked, which means that it will not be delivered
until it is later unblocked.  Between the time when it is generated
and when it is delivered a signal is said to be pending.
_

ブロックされたシグナルセットと無視されたシグナルセットの両方が子プロセスによって継承されるため、アプリケーションの親プロセスがこれらのシグナルの1つを無視またはブロックした可能性があります。

プロセスが前の信号の処理を完了する前に複数の信号が配信されるとどうなりますか?それはOSに依存します。上記でリンクされているsignal(2)のマンページで説明しています。

  • System Vは、信号処理をデフォルトにリセットします。さらに悪いことに、複数の信号をすばやく配信すると、再帰的な呼び出し(?)が発生します。
  • BSDは、ハンドラが完了するまで、シグナルを自動的にブロックします。
  • Linuxでは、これはGNU libcに設定されたコンパイルフラグに依存しますが、BSDの動作を期待します。
8
muru

送信されたすべての信号が配信されるとは信じられません。たとえば、終了した子プロセスからのSIGCHLDの処理にプロセスに長い時間がかかる場合、 linuxカーネル "coalesces" SIGCHLD になります。

あなたの質問の別の部分に答えるために、いくつかの異なるシグナルが間隔が短すぎて到着した場合、シグナルはカーネル内で「キュー」に入れられます。

_sa_sigaction_引数の_siginfo_t_メンバーを慎重に設定し、_sa_mask_の_siginfo_t_メンバーを使用してシグナルハンドラーを設定するには、sigaction()を使用する必要があります。これは少なくとも「非同期」信号のすべてをマスクすることを意味すると思います。 Linuxのマニュアルページsigaction()によると、処理される信号もマスクされます。 _sa_flags_メンバーをSA_SIGINFOに設定する必要があると思いますが、なぜこの迷信があるのか​​思い出せません。これにより、プロセスに、競合状態なしで設定されたままのシグナルハンドラー、および他のほとんどのシグナルによって中断されないシグナルハンドラーが提供されると思います。

シグナルハンドラー関数を非常に慎重に記述します。基本的には、グローバル変数を設定して、シグナルがキャッチされたことを示し、残りのプロセスでそのシグナルに必要なアクションを処理します。信号はそのようにして最短時間だけマスクされます。

また、信号処理コードを非常に徹底的にテストする必要があります。小さなテストプロセスに入れて、SIGUSR1およびSIGUSR2信号をできるだけ多く送信します。2つまたは3つの特別な目的の信号送信プログラムから送信される可能性があります。コードがSIGUSR1とSIGUSR2を迅速かつ正確に処理できることを確認したら、他のいくつかの信号も混ぜます。難しいデバッグに備える。

Linuxを使用していてLinuxのみを使用している場合は、signalfd()を使用してファイル記述子を作成し、select()またはポーリングしてこれらの信号を受信することを検討する場合があります。 signalfd()を使用すると、デバッグが容易になる場合があります。

7
Bruce Ediger

プロセスがkillを正常に呼び出した場合、ターゲットがシグナルを受信するという意味で、シグナルは確実に配信されます。これは非同期です。送信者は、信号がいつ受信または処理されたかを知る方法がありません。ただし、これは信号が配信されることを保証するものではありません。ターゲットは、信号を処理する前に停止する可能性があります。ターゲットが配信時にシグナルを無視している場合、シグナルは効果がありません。ターゲットがそれらを処理する前に同じシグナル番号の複数のインスタンスを受信する場合、シグナルはマージされる場合があります(通常はマージされます)。同じシグナルをプロセスに2回送信する場合、プロセスがシグナルを受信するかどうかはわかりません。一回か二回。シグナルは、ほとんどの場合、プロセスを強制終了するように設計されているか、プロセスに注意を払う方法として設計されています。これらは、通信自体のために設計されたものではありません。

信頼できる配信が必要な場合は、別の通信メカニズムが必要です。プロセス間の主な通信メカニズムは2つあります。a pipe は単方向通信を許可します。 a socket は、同じサーバーへの双方向通信と複数の接続を許可します。ターゲットが送信する通知と同じ数の通知を処理する必要がある場合は、パイプを介してバイトを送信します。

ブロックされている間に複数のシグナルが配信された場合、カーネルは標準シグナルを自由に合体できます。一方、リアルタイム信号には同様の障害はありません。

signal(7)マニュアルページ から:

リアルタイム信号は、以下によって区別されます。

  1. リアルタイム信号の複数のインスタンスをキューに入れることができます。対照的に、そのシグナルが現在ブロックされている間に標準シグナルの複数のインスタンスが配信される場合、1つのインスタンスのみがキューに入れられます。

SIGRTMINからSIGRTMAXの範囲の数値の信号を使用してみてください。

2
Graham Rushton