テクノロジー · 実用ガイド

Python subprocess がタイムアウト後も子孫を残す?process group と pipe を監査する

terminate、group signal、再帰的 cleanup を選ぶ前に、direct child、descendants、session、PGID、継承 pipe writer を追跡する。

Original diagram mapping a Python parent, direct child, descendants and inherited pipe writer
オリジナルイラスト:signal 前に process、group、pipe の ownership boundary を描く。 Watch at Ease

タイムアウトは待機が期限を超えたことだけを示し、仕事が一つの PID だけか、全子孫が同じ group にいるか、stdout と stderr の writer が消えたかは証明しない。

一つの launch token で topology と pipe state を保存し、仕事を本当に所有する最小の platform primitive を使う。短い grace period 後にだけ escalation し、実際の launcher で exit と closure を確認する。

cleanup 前に証拠を固定する

launch token、親と direct child の PID、PPID chain、command、start time、session、PGID、shell/capture 設定を leader 終了前に記録する。

leader の生死、残存 descendants、communicate が open pipe を待つかを別々に記録する。

PID ではなく ownership unit を選ぶ

単一 process なら direct-child contract で足りるが、shell、worker、build tool では POSIX group、recursive set、Windows job などを定義する。

未確認 PID から推測した group を signal しない。leader と membership を記録し、無関係な service を外す。

自分が作った POSIX group だけを制御する

tree 全体を所有する場合は start_new_session=True を使える。timeout 後は確認済み group に graceful signal、bounded wait、escalation、reap の順で行う。

threaded app で preexec_fn を安易に使わず、documented parameter を使う。descendant が別 session を作る可能性も再確認する。

継承 pipe を別の shutdown gate にする

全 writer が閉じるまで capture pipe は EOF にならない。shell や helper は direct child 終了後も handle を保持できる。

TimeoutExpired の partial output を保存し、確認済み writer を処理してから drain する。

platform branch で結果を証明する

適切な group がない場合、psutil で早期に recursive descendants を snapshot し、terminate、wait、kill と identity check を行う。

実 launcher で timeout を再現し、child/tree 消滅、pipe closure、output policy、reap、unrelated sentinel 生存を確認する。

Original decision diagram for leader reaping, descendant exit, pipe closure and collateral safety
オリジナルイラスト:四つの timeout acceptance gate をすべて確認する。 Watch at Ease