10月25日の更新:
今、私は問題の原因を突き止めました。
1)子プロセスはそれ自体を強制終了します。そのため、strace/perf/auditctlはそれを追跡できません。
2)プロセスを作成するためのJNI呼び出しは、Javaスレッドからトリガーされます。スレッドが最終的に終了すると、作成したプロセスも破棄されます。
3)子プロセスをforkおよびexecve()するコードには、次の行で親プロセスの停止を監視し、子プロセスを強制終了するコードがあります。prctl(PR_SET_PDEATHSIG、SIGKILL); b/cの前にこのフラグに特別な注意を払わなかったという私の欠点は、子プロセスがメインスレッドからフォークされる他のプロジェクトのベストプラクティスと見なされています。
4)この行をコメントアウトすると、問題はなくなります。元の目的は、親プロセスがなくなったときに子プロセスを強制終了することです。このフラグがなくても、それは正しい動作です。 ubuntuボックスのデフォルトの動作のようです。
5)ついに、カーネルバージョン3.4.0で修正されたカーネルバグであることがわかりました。AWSのubuntuボックスはカーネルバージョン3.13.0-29-genericです。
問題への便利なリンクがいくつかあります。
a) http://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them
b) prctl(PR_SET_PDEATHSIG、SIGNAL)は、親プロセスの出口ではなく、親スレッドの出口で呼び出されます 。
c) https://bugzilla.kernel.org/show_bug.cgi?id=433
10月15日の更新:
すべての提案をどうもありがとう。システムのある領域から別の領域へと調査しています。理由を見つけるのは難しい2。
私は2つのことを疑問に思っています。 1)strace、auditctl、perfスクリプトなどの強力なツールが、誰がキルを引き起こしたのかを追跡できないのはなぜですか?
2)+++がSIGKILLによって殺された+++は本当にシグナルから殺されたことを意味しますか?
元の投稿
Ubuntu12のJavaアプリケーションサーバーからJNIインターフェイスを介して起動された長時間実行Cプロセスがあります。Javaのプロセスビルダーではなく、JNIインターフェイスを使用してプロセスを開始する理由はb/cです。 JavaプロセスビルダーがIPC特にb/cの余分なバッファリングを行うと、非常に長い遅延が発生します。
定期的にSIGKILLによって不思議なことに終了します。私が見つけた方法は、「+++がSIGKILL +++によって殺された」というstraceを介したものです。
私は以下をチェックしました:
終了した理由に戸惑います。誰かがそれを追跡する方法について良い提案がありますか?
p.s.
私のubuntuの制限で-結果は次のとおりです:
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 7862
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 65535
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 7862
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
制限を引き上げようとしましたが、それでも問題は解決しません。
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) unlimited
max locked memory (kbytes, -l) unlimited
max memory size (kbytes, -m) unlimited
open files (-n) 65535
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) unlimited
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) unlimited
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
Cat/proc/$$$/statusを実行したときのprocステータスは次のとおりです
Name: mimi_coso
State: S (Sleeping)
Tgid: 2557
Ngid: 0
Pid: 2557
PPid: 2229
TracerPid: 0
Uid: 0 0 0 0
Gid: 0 0 0 0
FDSize: 256
Groups: 0
VmPeak: 146840 kB
VmSize: 144252 kB
VmLck: 0 kB
VmPin: 0 kB
VmHWM: 36344 kB
VmRSS: 34792 kB
VmData: 45728 kB
VmStk: 136 kB
VmExe: 116 kB
VmLib: 23832 kB
VmPTE: 292 kB
VmSwap: 0 kB
Threads: 1
SigQ: 0/7862
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000004
SigIgn: 0000000000011001
SigCgt: 00000001c00064ee
CapInh: 0000000000000000
CapPrm: 0000001fffffffff
CapEff: 0000001fffffffff
CapBnd: 0000001fffffffff
Seccomp: 0
Cpus_allowed: 7fff
Cpus_allowed_list: 0-14
Mems_allowed: 00000000,00000001
Mems_allowed_list: 0
voluntary_ctxt_switches: 16978
nonvoluntary_ctxt_switches: 52120
straceの表示:
$ strace -p 22254 -s 80 -o /tmp/debug.lighttpd.txt
read(0, "SGI\0\1\0\0\0\1\0c\0\0\0\t\0\0T\1\2248\0\0\0\0'\1\0\0(\0\0"..., 512) = 113
read(0, "SGI\0\1\0\0\0\1\0\262\1\0\0\10\0\1\243\1\224L\0\0\0\0/\377\373\222D\231\214"..., 512) = 448
sendto(3, "<15>Oct 10 18:34:01 MixCoder[271"..., 107, MSG_NOSIGNAL, NULL, 0) = 107
write(1, "SGO\0\0\0\0 \272\1\0\0\t\0\1\253\1\243\273\0\0\0\0'\1\0\0\0\0\0\1\242"..., 454) = 454
sendto(3, "<15>Oct 10 18:34:01 MixCoder[271"..., 107, MSG_NOSIGNAL, NULL, 0) = 107
write(1, "SGO\0\0\0\0 \341\0\0\0\10\0\0\322\1\254Z\0\0\0\0/\377\373R\4\0\17\21!"..., 237) = 237
read(0, "SGI\0\1\0\0\0\1\0)\3\0\0\t\0\3\32\1\224`\0\0\0\0'\1\0\0\310\0\0"..., 512) = 512
read(0, "\344u\233\16\257\341\315\254\272\300\351\302\324\263\212\351\225\365\1\241\225\3+\276J\273\37R\234R\362z"..., 512) = 311
read(0, "SGI\0\1\0\0\0\1\0\262\1\0\0\10\0\1\243\1\224f\0\0\0\0/\377\373\222d[\210"..., 512) = 448
sendto(3, "<15>Oct 10 18:34:01 MixCoder[271"..., 107, MSG_NOSIGNAL, NULL, 0) = 107
write(1, "SGO\0\0\0\0 %!\0\0\t\0\0+\1\243\335\0\0\0\0\27\0\0\0\0\1B\300\36"..., 8497) = 8497
sendto(3, "<15>Oct 10 18:34:01 MixCoder[271"..., 107, MSG_NOSIGNAL, NULL, 0) = 107
write(1, "SGO\0\0\0\0 \341\0\0\0\10\0\0\322\1\254t\0\0\0\0/\377\373R\4\0\17\301\31"..., 237) = 237
read(0, "SGI\0\1\0\0\0\1\0\262\1\0\0\10\0\1\243\1\224\200\0\0\0\0/\377\373\222d/\200"..., 512) = 448
sendto(3, "<15>Oct 10 18:34:01 MixCoder[271"..., 107, MSG_NOSIGNAL, NULL, 0) = 107
write(1, "SGO\0\0\0\0 \341\0\0\0\10\0\0\322\1\254\216\0\0\0\0/\377\373R\4\0\17\361+"..., 237) = 237
read(0, "SGI\0\1\0\0\0\1\0\221\0\0\0\t\0\0\202\1\224\210\0\0\0\0'\1\0\0P\0\0"..., 512) = 159
read(0, unfinished ...)
+++ killed by SIGKILL +++
ついにその理由がわかりました。
子プロセスはそれ自体を強制終了し、それはLinuxカーネルのバグです。
詳細:
1)子プロセスはそれ自体を強制終了します。そのため、strace/perf/auditctlはそれを追跡できません。
2)プロセスを作成するためのJNI呼び出しは、Javaスレッドからトリガーされます。スレッドが最終的に終了すると、作成したプロセスも破棄されます。
3)子プロセスをforkおよびexecve()するコードには、次の行で親プロセスの停止を監視し、子プロセスを強制終了するコードがあります。prctl(PR_SET_PDEATHSIG、SIGKILL); b/cがメインスレッドから子プロセスがフォークされる他のプロジェクトのベストプラクティスと見なされる前は、このフラグに特別な注意を払っていませんでした。
4)この行をコメントアウトすると、問題はなくなります。元の目的は、親プロセスがなくなったときに子プロセスを強制終了することです。このフラグがなくても、それは正しい動作です。 ubuntuボックスのデフォルトの動作のようです。
5)この記事から、 https://bugzilla.kernel.org/show_bug.cgi?id=433 。これはカーネルのバグであり、カーネルバージョン3.4.0で修正されています。AWSのubuntuボックスはカーネルバージョン3.13.0-29-genericです。
私のマシン構成:===> Ubuntu 14.04 LTS ===> 3.13.0-29-一般
問題へのいくつかの有用なリンク:
a) http://www.linuxprogrammingblog.com/threads-and-fork-think-twice-before-using-them
b) prctl(PR_SET_PDEATHSIG、SIGNAL)は、親プロセスの出口ではなく、親スレッドの出口で呼び出されます
マシンにルートアクセス権があると仮定すると、kill(2)syscallの監査を有効にして、そのような情報を収集できます。
root # auditctl -a exit,always -F Arch=b64 -S kill -F a1=9
root # auditctl -l
LIST_RULES: exit,always Arch=3221225534 (0xc000003e) a1=9 (0x9) syscall=kill
root # sleep 99999 &
[2] 11688
root # kill -9 11688
root # ausearch -sc kill
time->Tue Oct 14 00:38:44 2014
type=OBJ_PID msg=audit(1413272324.413:441376): opid=11688 oauid=52872 ouid=0 oses=20 ocomm="sleep"
type=SYSCALL msg=audit(1413272324.413:441376): Arch=c000003e syscall=62 success=yes exit=0 a0=2da8 a1=9 a2=0 a3=0 items=0 ppid=6107 pid=6108 auid=52872 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsg
id=0 tty=pts2 ses=20 comm="bash" exe="/bin/bash" key=(null)
もう1つの方法は、カーネルトレースを設定することです。これは、監査システムが同じ作業を実行できる場合、やり過ぎになる可能性があります。
前に述べたように、もう1つの選択肢は、カーネルトレースを使用することです。これは、perfツールで実行できます。
# apt-get install linux-tools-3.13.0-35-generic
# perf list | grep kill
syscalls:sys_enter_kill [Tracepoint event]
syscalls:sys_exit_kill [Tracepoint event]
syscalls:sys_enter_tgkill [Tracepoint event]
syscalls:sys_exit_tgkill [Tracepoint event]
syscalls:sys_enter_tkill [Tracepoint event]
syscalls:sys_exit_tkill [Tracepoint event]
# perf record -a -e syscalls:sys_enter_kill sleep 10
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 1.634 MB perf.data (~71381 samples) ]
// Open a new Shell to kill.
$ sleep 9999 &
[1] 2387
$ kill -9 2387
[1]+ Killed sleep 9999
$ echo $$
9014
// Dump the trace in your original Shell.
# perf script
...
bash 9014 [001] 1890350.544971: syscalls:sys_enter_kill: pid: 0x00000953, sig: 0x00000009