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


9

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

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

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

回答:


8

「信号が多すぎる」問題は別として、信号は明示的に無視できます。から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)議論し、それを上記のリンクmanページ:

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

4
Linuxのmanページでsignal(2)は、sigaction(2)代わりにを使用してこの混乱を回避することを強調しています。
Nate Eldredge、2015年

7

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

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

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

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

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

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


2
合体されるのはSIGCLDだけではありません。すべての信号は、処理する前に配信されると合体する可能性があります。
Gilles「SO-邪悪なことをやめなさい」2015

SIGCHLD信号の「長すぎる」時間の測定はありますか?現在、プログラムでこの動作が発生しており、シグナルハンドラーが100ミリ秒以上かかることはないと思います。
xrisk

@Rishav-私の知る限り、「長すぎる」とは何かを知る方法はありません。システム全体の負荷が重要だと思います。つまり、他のプロセスとカーネルが実行していることは、それらが合体するためのシグナル間の「時間」に影響します。役に立たない答えだと思います。
Bruce Ediger

6

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

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


4
シグナルが配信されないいくつかの方法(つまり、プロセスが受信される前に停止した、またはシグナルが合体した)について説明したので、「シグナルは確実に配信される」と書いたのですか?
ジョニー

2

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

以下からの信号(7)のマニュアルページ

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

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

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


リアルタイム信号には制限がありますが、非常に高いです。ユーザーが送信した未処理の保留中のシグナルの数がRLIMIT_SIGPENDINGを超えると、シグナルはドロップされます。ulimit -iUbuntu 18.04では、この値は63432と表示されます。
ベイン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.