daemontools管理サービスに対してTERMシグナルが効かなくなった時の対応
Overview
TERMシグナル
を送ってもpidが変わらない場合は、Killシグナル
をpidに送ってプロセス自体を落とす。- サービス自体はdaemontoolsで管理しているためkillされたサービスは自動で上げてくれるため再起動となる。
内容
daemontoolsに対してTERMシグナルを送っても効かなかったためその対応の記録です。
strace コマンドを利用し、特定プロセスのシステムコールレベルの処理をトレースしてみる
# strace -p 18043 Process 18043 attached - interrupt to quit clock_gettime(CLOCK_MONOTONIC, {21942263, 214411873}) = 0 clock_gettime(CLOCK_MONOTONIC, {21942263, 214454654}) = 0 epoll_wait(17, {}, 64, 9) = 0 clock_gettime(CLOCK_MONOTONIC, {21942263, 223633781}) = 0 clock_gettime(CLOCK_MONOTONIC, {21942263, 223668174}) = 0 epoll_wait(17, {}, 64, 1) = 0 clock_gettime(CLOCK_MONOTONIC, {21942263, 224836558}) = 0 clock_gettime(CLOCK_MONOTONIC, {21942263, 224875851}) = 0 epoll_wait(17, {}, 64, 999) = 0 clock_gettime(CLOCK_MONOTONIC, {21942264, 225003708}) = 0 clock_gettime(CLOCK_MONOTONIC, {21942264, 225060544}) = 0 epoll_wait(17, {}, 64, 999) = 0 clock_gettime(CLOCK_MONOTONIC, {21942265, 225225110}) = 0 clock_gettime(CLOCK_MONOTONIC, {21942265, 225266000}) = 0 epoll_wait(17, {}, 64, 999) = 0 clock_gettime(CLOCK_MONOTONIC, {21942266, 225429915}) = 0 clock_gettime(CLOCK_MONOTONIC, {21942266, 225469449}) = 0 epoll_wait(17, {}, 64, 998) = 0 clock_gettime(CLOCK_MONOTONIC, {21942267, 224646569}) = 0 clock_gettime(CLOCK_MONOTONIC, {21942267, 224699790}) = 0 futex(0x7ff830810644, FUTEX_WAKE_OP_PRIVATE, 1, 1, 0x7ff830810640, {FUTEX_OP_SET, 0, FUTEX_OP_CMP_GT, 1}) = 1 futex(0x7ff83081067c, FUTEX_WAIT_PRIVATE, 5703703, NULL) = -1 EAGAIN (Resource temporarily unavailable) write(6, "!", 1) = 1
EAGAIN (Resource temporarily unavailable)
なので、システムのプロセステーブルが多くなり fork(2) システムコールが失敗した、あるいはメモリーまたはスワップ空間が足りないためにシステムコールが失敗した可能性が高い。
svc -du
を行なったも同様の結果になる。
そのためTERMシグナルを送ってもpidが同様の場合は、daemontools管理のサービスpidを終了させる対応を入れる。
対象サービスは親プロセスに紐づいて子プロセスがいる。
$ pstree -A init-+-abrtd |-svscanboot(1681)-+-readproctitle(1713) | |-supervise(1724)---ruby(26456)-+-ruby(26473)-+-{ruby}(26475) | | | |-{ruby}(26483) | | | |-{ruby}(26485) | | | |-{ruby}(26487) | | | `-{ruby}(27879) | | `-{ruby}(26474)
親プロセス(26456
) だけをkillすると子プロセスがゾンビ化してしまう。
$ kill -9 26456 $ pstree -A |-ruby(26473)-+-{ruby}(26475) | |-{ruby}(26483) | |-{ruby}(26485) | |-{ruby}(26487) | `-{ruby}(27879)
親プロセスと子プロセスを一括で終了してくれるコマンドを探してみたが良さそうなのは見つけられなかった。
kill -SIGTERM -- -<PID>
=> 子は死なずにゾンビプロセスとなる。ルートに移行されるので利用できない。
pgrep
を利用すると子プロセス一覧を取得できるため
$ sudo ps auxf | grep fluentd root 1724 0.0 0.0 3992 476 ? S Jun17 0:01 | \_ supervise fluentd-audit root 11923 0.4 0.6 103484 23944 ? Sl 13:51 0:00 | | \_ /opt/td-agent/embedded/bin/ruby /usr/sbin/td-agent --use-v1-config -c /data/daemon/fluentd-audit/td-agent.conf -p /data/daemon/fluentd-audit/plugin root 11944 0.9 1.2 188112 51708 ? Sl 13:51 0:00 | | \_ /opt/td-agent/embedded/bin/ruby /usr/sbin/td-agent --use-v1-config -c /data/daemon/fluentd-audit/td-agent.conf -p /data/daemon/fluentd-audit/plugin root 12560 0.0 0.0 103304 1992 pts/1 S+ 13:52 0:00 \_ grep fluentd
親プロセスから子プロセス一覧を取得(pgrep -P <親プロセス>
)させ、svc -t
でも子プロセスが死なない場合は、子プロセスをkillする実装方針でコーディングを行い対応した。