SIGSTOPで停止したプロセスにSIGTERMを送ってもプロセスが死なない?
二十五日半狂乱3日目の記事
もはや、Advent Calendarでもなんでもなくなっているけど、そんな悲しい現実はさておいて.
前回の話がstackoverflowですでに議論され尽くされていて、解答の一つに自分のスクリプト似た構造のシェルスクリプトがあった.
#!/bin/bash killtree() { local _pid=$1 local _sig=${2:-TERM} kill -stop ${_pid} # needed to stop quickly forking parent from producing child between child killing and parent killing for _child in $(ps -o pid --no-headers --ppid ${_pid}); do killtree ${_child} ${_sig} done kill -${_sig} ${_pid} } if [ $# -eq 0 -o $# -gt 2 ]; then echo "Usage: $(basename $0) <pid> [signal]" exit 1 fi killtree $@
シグナルを指定できるし、親プロセスをstopしてから子スレッドの操作をするしで、悲しいかなこっちの方が断然良い出来だ.
そんなことを思いつつ、この投稿に対するコメントを眺めていると、
Stopped processes don't get killed with SIGTERM. See my answer – x-yuri Nov 20 '12 at 20:32
などという指摘があった.
中断したプロセスにkill TERMしてもプロセスが殺されないとは知らなかった.
もう少し遊んでみることにする.
SIGSTOPしたプロセスにSIGTERMしてみる
前回の記事で作成したmkpstree.bashでプロセスツリーを作ってそれに対して上記のkiltreeでいろんなシグナルを送信する.
このkilltreeはkillコマンドでシグナルを送信する前に予めSIGSTOPでプロセスを停止している点に注意しなければならない.
状況を把握するために、上記のkilltreeにecho "kill -${_sig} ${_pid}
てな感じのechoを仕込んで様子を観察してみる*1.
$ bash mkpstree.bash & [1] 4609 $ pstree -pha 4609 bash,4609 mkpstree.bash |-sleep,4610 12345 |-sleep,4611 12345 |-sleep,4612 67890 |-sleep,4613 67890 `-sleep,4614 10000 $ bash killtree.bash 4609 kill -TERM 4610 kill -TERM 4611 kill -TERM 4612 kill -TERM 4613 kill -TERM 4614 kill -TERM 4609 [1]+ Stopped bash mkpstree.bash
確かに、TERMを送ってStoppedとはこれ如何に.
停止しているんだから再開してみた.
$ bash killtree.bash 4609 CONT kill -CONT 4610 kill -CONT 4611 kill -CONT 4612 kill -CONT 4613 kill -CONT 4614 kill -CONT 4609 [1]+ Terminated bash mkpstree.bash
なんと再開したらTerminatedとなった.
sleep 100 &
などの適当なプロセスに対して、SIGSTOP、SIGTERM、SIGCONTの順でシグナルを送っても同じ状況を再現できる.
これは単にSIGTERMのポリシー的に、プロセス終了時の後始末をきっちり出来ない以上、強制終了などという暴挙には移れないということだろうか?うーん.
SIGKILLしてみる
stackoverflowのコメントに、殺したければSIGKILLを送れば良くないか?とあったのでSIGKILLも送ってみる.
$ bash mkpstree.bash & [1] 4632 $ pstree -pha 4632 bash,4632 mkpstree.bash |-sleep,4633 12345 |-sleep,4634 12345 |-sleep,4635 67890 |-sleep,4636 67890 `-sleep,4637 10000 $ bash killtree.bash 4632 KILL kill -KILL 4633 kill -KILL 4634 kill -KILL 4635 kill -KILL 4636 kill -KILL 4637 kill -KILL 4632 [1]+ Killed bash mkpstree.bash
無事に一発でプロセスツリーをkillできた.
しかしまぁ、このkilltreeは自分が作ったものなんかよりも余程便利な代物である.
*1:ここではシグナルの名前をSIGTERMからTERMに省略している