2

POSIX(Linux)環境で動作するアプリケーションについてです。ほとんどのシグナル (例: Ctrl+ C- シグナル 2、SIGINT) が処理され、その他のシグナルはほとんど処理されません。それが完了するexit()と、望ましい終了コードでシステム コールがハンドラから呼び出されます。

ただし、Signal 9 や Signal 15 などの一部の信号は処理できません。

残念ながら、特定のアプリケーションを起動する親プロセス (外部スクリプト) は、シグナル 9 または 15 が終了の理由であるかどうかを認識し、クリーンアップする必要があります。

上記を知るために親プロセスが受け取ることができる定義済みの終了コードはありますか?

アプリを起動するスクリプトは bash_script です。アプリケーション自体は C です。

4

3 に答える 3

5

The return status from wait() or waitpid() encodes the information you need.

The POSIX macros are:

  • WIFEXITED(status) returns true if the child exited via exit() or one of its relatives.
  • WEXITSTATUS(status) tells you what that exit status was (0..255).
  • WIFSIGNALED(status) returns true if the child exited because of a signal (any signal).
  • WTERMSIG(status) returns the signal number that killed the child.

The non-standard but common macro WCOREDUMP(status) tells you if the process dumped core. You can also tell whether status reflect that the process was stopped, or continued (and what the stop signal was).

Note that signal 15 is usually SIGTERM and SIGTERM can be trapped by an application. The signals that cannot be trapped are SIGKILL (9) and SIGSTOP (17 on Mac OS X; may not be the same everywhere).


The question then is if bash provides this info for a script.

The answer is yes, but only indirectly and not 100% unambiguously. The status value reported by bash will be 128 + <signum> for processes that terminate due to signal <signum>, but you can't distinguish between a process that exits with status 130, say, and a process that was interrupted by SIGINT, aka signal 2.

于 2012-11-16T05:11:02.757 に答える
2

15 ( SIGTERM) は、アプリケーションがそのように選択した場合、アプリケーションによってキャッチされて処理される可能性がありますが、おそらく現時点ではそうではありません

9 ( SIGKILL) は明らかにどのアプリケーションでもキャッチできません。

ただし、通常、オペレーティング システムは、プロセスを終了させたシグナルを識別できるように終了ステータスを設定します。通常、exit(3) 関数 [したがって _exit(2) システム コール] への status パラメータの下位 8 ビットのみが、statuswait(2) によって親プロセス (外部スクリプトを実行するシェル) に返される値にコピーされます。あなたの例では)。そのため、OS が終了したプロセスに関する他の情報を入力するために使用する値に、sizeof(int)-1バイト単位のスペースが残ります。status通常、wait(2) のマニュアル ページには、待機ステータスを解釈する方法が記述されているため、プロセスが終了した場合に、プロセスが _exit(2) に渡したステータスからプロセス終了に関する追加情報を分割します。

残念ながら、この追加情報をスクリプトで利用できるようにするかどうかは、スクリプトを実行するシェルがそれを処理する方法によって異なります。

解釈方法の詳細については、最初にシェルのマニュアル ページを確認してください$?

シェルがstatus int値全体をスクリプトで (変数内で) 逐語的に使用$?できるようにすると、値を解析して、プログラムが終了した方法と理由を判別できます。ほとんどのシェルはこれを完全に行っているようには見えません (そして、さまざまな理由で、少なくとも標準への準拠である可能性があります) が、少なくともクエリを解決できるようにするのに十分なほどのことを行っています (そして、POSIX である必要があります)。互換性)。

ここでは、たとえば、Mac OS X で KSH の AT&T バージョンを実行しています。私の ksh(1) マニュアル ページには、プログラムが正常に終了した場合の終了ステータスは 0-255 であると書かれています (値はおそらく渡されたものです)。 _exit(2)) および 256+signum (プロセスがシグナル ("signum" の番号) によって終了された場合)。Linux についてはわかりませんが、OS X では、bash は Ksh とは異なる終了ステータスを返します (bash は 8 番目のビットを使用してシグナルを表すため、有効な終了値として 0-127 のみを許可します)。(_exit(2) の 8 つの下位ビットが使用可能であるという wait(2) の主張と、シェルによる待機ステータスの$?7 ビットのみを保持します。図に行く!Ksh の動作は POSIX に違反していますが、厳密に互換性のあるシェルでは、プロセスが _exit(2) に 128 ~ 255 の値を渡していることと、シグナルによって終了したことを区別できない可能性があるため、より安全です。)

とにかく、catプロセスを開始SIGQUITし、端末から送信します (^ を押して) (端末のキーボードからSIGQUIT送信する簡単な方法がないため、使用します)。SIGTERM

22:01 [2389] $ cat
^\Quit(coredump)
ksh: exit code: 259

EXIT( $? がゼロでない場合に $? を出力するように定義されたシェルトラップがあるので、上記にも表示されます)

22:01 [2390] $ echo $?
259

(259 は、wait(2) によってシェルに返されるステータスを表す整数値です)

22:02 [2391] $ bc
obase=16
259
103
^D22:03 [2392] $ 

(259 には 16 進値 0x0103 があることを確認してください。0x0100 は 256 10 進数であることに注意してください)

22:03 [2392] $ signo SIGQUIT    
#define SIGQUIT 3   /* quit */

signo(ヘッダーを検索してシンボリック シグナル名を表す番号を見つけるというシェル エイリアスがあります。ここで、ステータス値の 0x03 が と同じ番号であることを確認してくださいSIGQUIT。)

wait(2) システム コールと関連するマクロをさらに調べると<sys/wait.h>、何が起こっているのかをもう少し理解できるようになります。

C では、待機ステータスをデコードするための基本的なロジックは、次のマクロを使用します<sys/wait.h>

if (!WIFEXITED(status)) {
        if (WIFSIGNALED(status)) {
                termsig = WTERMSIG(status);
        } else if (WIFSTOPPED(status)) {
                stopsig = WSTOPSIG(status);
        }
} else {
        exit_value = WEXITSTATUS(status));
}

それが役立つことを願っています!

于 2012-11-16T06:07:13.730 に答える
0

親プロセスが SIGKILL またはシグナル 9 を検出することはできません - SIGNAL がユーザー空間の外で発生した場合。

提案は、子プロセスがなくなったかどうかを親プロセスに検出させ、それに応じて処理させることです。素晴らしい例は、mysqld-safe などに見られます。

于 2012-11-16T05:06:09.557 に答える