浅葱さんのブログ

ええ、以前はぷらしのすとか言っていましたよ

exitcode137

さっきあるシステム障害があって、 exit code 137 と見てすぐに SIGKILL でやられたな、といったらどういう魔法じゃと言われた。存外常識ではないらしいので書いておく。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

UNIXのプロセスには親プロセスがあります。ps(1) の PPID 欄でみたり、Linuxならpstree(1)で木構造表示したりできます。
親はふつう、子がどうなったか知るため wait(2) で待ちます(待ってもらえない子はゾンビになります)。
すると子が死んだときに wait の引数のポインタが指す int にいろんなビットフィールドが入るのですが、
どこかの8ビットが終了ステータス(子のexit(2)の引数の下位8ビット、あるいはシグナルで死んだ場合はシグナル番号)、
別のどこかに「シグナルを食らった」ことを示すビットなどが入っています
(具体的構造は man には書いていません。ヘッダファイルを読めばすぐにわかりますが、その解析結果をあてにしたプログラムを書いてはいけないという意味です)。で、シェルは、終了ステータスを $? にセットするという
のですが、たいていの UNIX では具体的にはこの8ビットと、シグナルで死んだ場合には 128 を or したものを使います。

たいていの、と逃げを打つうゆえんは、UNIX と称するために適合しなければならない


POSIX 規格では「シグナルで終了した場合には128を超える値とせねばならない」としか書かれていない
http://pubs.opengroup.org/onlinepubs/007904875/utilities/xcu_chap02.html#tag_02_08_02
からです、が、実際問題として上記の「128 を or する」ロジック以外の UNIX は知りません。

SIGKILL のシグナル番号も、Linux のマニュアルに 9 と書いてありますが、POSIX
規格で保証されたものではないはずです。が、
$ kill -9 pid
というコマンドがあまりにも普及しているため、9 以外を使っている UNIX ベンダーはないものと思われます。

で、プログラムが SIGKILL を受けて死ぬと親たるシェルの $? は 128 + 9 = 137 となるわけです。

なお、少なくとも AIX の Korn シェルと Linux の Bash は子がシグナルで死んだ場合にだけ
標準エラー出力に "Killed\n" と出力するので、wait のくれる整数値を解析してシグナルで死んだことを判定しているのですが、
その情報はたぶん使い捨てられていて、シェルプログラムからは子が SIGKILL で殺されたのか、子が exit 137 といって自殺したのかを判別
する方法はありません、少なくとも知りません。
スポンサーサイト

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://prasinos.blog2.fc2.com/tb.php/773-e4be2036
この記事にトラックバックする(FC2ブログユーザー)

FC2Ad