Skip to content

Instantly share code, notes, and snippets.

@fortune
Last active January 14, 2021 05:24
Show Gist options
  • Save fortune/23b24df0e0b9e80b9cdfbfd9d534ca0f to your computer and use it in GitHub Desktop.
Save fortune/23b24df0e0b9e80b9cdfbfd9d534ca0f to your computer and use it in GitHub Desktop.
プロセスの終了ステータスと Python の multiprocessing モジュール

Python とプロセスの終了ステータス

C 言語でプログラムを書き、

return 0;
return 5;
return 255;
exit(100);
_exit(0);

のように main 関数から整数値を返したり、exit_exit に整数値を指定してで終了すると、その整数値の下位8ビットがプロセスの終了ステータスになる。つまり、整数 n で終了したなら、

n & 0377

が終了ステータスになる。この終了ステータスは、シェル変数なら、$? で取得できるし、親プロセスで wait システムコールを使っているなら、WIFEXITED マクロ(子プロセスが正常終了した場合に真を返す)、WEXITSTATUS マクロ(子プロセスの終了ステータスを返す) を使って取得できる。なお、シェル変数 $? をシェル上で出力する場合、符号なしの8ビット整数として解釈するので

return 256;	// $? は 0 になる。
return 257;	// $? は 1 になる。
return -1;	// $? は 255 になる。

となる。

return 文や exit, _exit 関数のような正常終了ではなく、異常終了、つまりシグナルで終了した場合、終了ステータスに相当する 8 ビットには、最上位ビットに 1 がセットされ、残りの7ビットにシグナル番号がセットされる。したがって、異常終了したプロセスのシェル変数 $? は 128 + シグナル番号になる。たとえば、シグナル番号 1 の SIGHUP をプロセスID が 6014 のプロセスに送って

$ sleep 120    # 終了をまたずに別のシェルから kill -HUP 6014 とする。
$ echo $?
129

のように、129 = 128 + 1 になる。親プロセスで wait システムコールを使っているなら、WIFSIGNALED マクロ(子プロセスが異常終了したなら真を返す)、WTERMSIG マクロ(シグナル番号を返す) で異常終了か否か、異常終了だったときのシグナル番号を調べられる。

まとめると、プロセスの終了ステータスは、0 〜 127 の範囲に制限した方がいい。128 以上や負の値にしてしまうと、シェル変数 $? では異常終了の場合と区別できないからだ。

Python プログラムで

import sys

sys.exit(n)

で終了すると、これは C プログラムで exit(n) で終了するのと同じになる。明示的に sys.exit(n) を呼び出さずに終了した場合、終了ステータスが 0 で正常終了する。

python プロセス内で 8/0 のようにして例外で終了させると、プロセス自体は正常終了で、終了ステータスは 1 になる。

multiprocessing.Process で子プロセスを作って開始した場合、その子プロセスの終了ステータスは、Process.exitcode で取得できる。これは、

  • 子プロセスが sys.exit(n) で終了したなら n になる。

  • 子プロセスが sys.exit(n) を明示的に使わずに正常終了したなら、0 になる。

  • 子プロセスが例外で終了したなら、1 になる。

  • 子プロセスがシグナル番号 N により終了(異常終了)したなら、-N になる。

したがって、Python コードで Process.exitcode を使って子プロセスの終了状態を知らせたい場合、0, または 2 〜 127 を使うといい。なお、親プロセスで子プロセスの Process.exitcode を取得しないと、子プロセスがゾンビプロセスになるようだ。

実は、Python の sys.exit(n) は、SystemExit という BaseException 直下の例外をスローしている。プログラムがこの例外で終了した場合、Python は、 C 言語の exit(n) で終了する。こういう例外は、プログラムでキャッチすべきではない。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment