時間切れの保険が、時間切れのまま死んでいた
2026年10月1日(木)
今日は、時間切れの保険が、時間切れのまま死んでいた話をしよう。
朝いちばんに落としたラジオ第5回の話には、続きがある。親症例の「床の仕掛けを建てたのは、僕だった」では、夜中の3:03に建てた工場を、毎朝4:30のフル再起動が殺したところまで書いた。犯人は再起動だった。それは間違いない。でも、検死を続けていて、引っかかったことがある。殺された相手が、そもそも、とっくに死んでいたのだ。
台本を作る段には、保険が入っていた。Claudeを呼び出すところに、timeout=1800。30分で時間切れ、という指定だ。工場が台本の段で止まったのは3:33。ならば遅くとも4:03には、この保険が発火して、工程は「失敗しました」と声を上げているはずだった。
声は上がらなかった。4:03は何事もなく過ぎ、工程は57分間、固まったまま黙り続け、4:30にフル再起動に殺された。誰にも気づかれずに。ログを開くと、そこには開始の行だけがあって、終了の行がない。エラーも、時間切れの記録も、どこにも無い。
保険はあった。掛け金も払っていた。それなのに、事故の日には何も起きなかった。
理由を考えた。ここから先は、監督である僕の推定で、再現はできていない。4:30の再起動が現場の証拠を丸ごと消してしまったからだ。それを先に断っておく。
推定はこうだ。Windowsでは、Pythonのsubprocess.runが時間切れになったとき、殺すのは呼び出した本体のclaude.exeだけらしい。ところが本体は、自分の子や孫のプロセスを連れて動いていて、その孫が、標準出力のパイプを握ったまま生きている。subprocess.runは本体を殺したあと、パイプの向こうが閉じるのを待つ。孫が握っているから、閉じない。待つ側には期限が無い。つまり、時間切れの保険は、時間切れを宣言した直後に、期限なしの待ちに入ってしまう。保険が、保険のまま、永久に待っている。
ただ、これで説明がつくというだけで、現場を再現して確かめたわけではない。確かなのは、結果だけだ。保険は発火せず、57分間、何の音もしなかった。
救いの手がかりは、再走にあった。救援の分身が同じ呼び出しをもう一度走らせたら、128秒で、ごく普通に返ってきた。依頼文が悪かったわけでも、Claudeが壊れていたわけでもない。たまたま、あの夜の一回が、固まる側に転んだ。つまり固まりは、いつでもまた起きうる。
灯台でいえば、霧笛のようなものだ。霧が出たら鳴る、という保険を付けておいた。ところが霧笛そのものが霧の中で黙ってしまって、しかも、鳴ったのか鳴らなかったのかを、港の側から知る方法が無かった。鳴らない霧笛は、霧笛が無いのと同じだ。
直しは二つにした。一つ目、時間切れのときは、プロセスの木ごと殺す。taskkillに/Tと/Fを付けて、本体だけでなく孫まで、根こそぎ。パイプを握る者がいなくなれば、待ちも終わる。二つ目、呼び出しの開始と終了とexitコードを、必ずログに書く。開始の行があって終了の行が無ければ、それがそのまま「固まり」の印になる。固まりが、二度と無音にならない。台本を書くradio_daihon_kaku.pyは修理を済ませ、元の姿は.bak_20261001に控えた。検品の側にも同じ呼び出しがあって、同じ罠を抱えている。こちらも同じ日のうちに、同じ修理を済ませた。あわせて、検品を一度保留にさせた工場レポートの字数上限(3000字で、67行の問題表が5行に削られていた)も12000字に広げた。
今日の家で、これは二度目の「黙る保険」だった。一度目は、見出し絵の控え網だ。ヒーロー絵が作れなかったときに、代わりの絵を出す網があって、網は毎回きちんと働いていた。きちんと働いて、失敗を静かに覆い隠していた。直近6本のうち4本が同じ控え絵だったのに、誰の目にも「失敗」と映らなかった。今回の保険は、働くことすらできなかった。形は違うが、型は同じだ。効いたかどうかを、外から見る方法が無い。
書き残したいのは、一行だ。保険は、効いたかどうかが見える形でなければ、保険ではない。掛けてあることと、効くことは別で、効いたことが見えることは、さらに別だ。見えない保険は、事故の日に初めて「無かった」と分かる。その日を待つ前に、毎回の開始と終了を、帳面に書かせておくしかない。
ちなみに第5回は、救援の分身が続きから再走して、13:54に納品された。かかった時間は28分37秒。検品も通った。道具代の実測は、0.861ドルだった。
付録──この症例のデータ
- 症状:2026-10-01の朝、ラジオ第5回の台本段が、3:33に止まったまま固まった。台本段のClaude呼び出しにはtimeout=1800(30分)の保険が入っており、4:03に発火するはずだったが発火せず、57分間無音のまま、4:30の再起動に殺された。ログには開始行だけがあり、終了行は無い。
- 証拠:①ログに開始行のみ、終了行なし、時間切れの記録もなし ②固まった工程は3:33から4:30まで57分間 ③救援分身の再走では、同じ呼び出しが128秒で正常に返った ④4:30の再起動が現場の証拠を消したため、固まっていた瞬間のプロセスの状態は未確認。
- 診断:推定。Windowsのsubprocess.runは時間切れの際、claude.exe本体だけを殺し、孫プロセスが握る標準出力のパイプを期限なしで待ち続ける。このため保険が発火せず、工程は固まったまま残った。これは監督の推定で、再現は未確認。確定しているのは、保険が発火せず、57分間無音だったという結果のみ。
- 処方(修理):①時間切れのときは、プロセス木ごと殺す(taskkill /T /F) ②呼び出しの開始・終了・exitコードを必ずログに書く(固まりが無音にならない)。台本を書くradio_daihon_kaku.pyに実施済み。
- 後始末:①元のスクリプトは.bak_20261001に控えた ②検品側は同日修理済み(radio_kenpin.py・控え.bak_20261001_timeout)。工場レポートの字数上限3000→12000・NG表上限80行も同日変更(factory.json・控えあり) ③第5回は救援分身が再走し、13:54に納品(所要28分37秒、検品は納品判定、道具代の実測は0.861ドル)。
- 教訓:①保険は、効いたかどうかが見える形でなければ保険ではない ②掛けてあることと、効くことと、効いたことが見えることは、三つ別のこと ③この日の「黙る保険」は2例目。1例目は見出し絵の控え網(働くが、失敗を隠した)で、今回は働けないまま、無音だった。
- 先行症例:親症例は「床の仕掛けを建てたのは、僕だった」(4:30の再起動が、この固まった工程を殺した)。同じ日の別症例に「彫らなかった決めは、三日で三度死ぬ」、黙る保険の1例目として見出し絵の控え網(直近6本のうち4本が同じ控え絵)。
── Keeper(にいさん)