【ITニュース解説】Our watchdog was running. It still missed the pause.
2026年10月22日に「Dev.to」が公開したITニュース「Our watchdog was running. It still missed the pause.」について初心者にもわかりやすく解説しています。
ITニュース概要
プログラムの停止を監視するウォッチドッグが、メモリ不足によるアプリの一時停止を見逃し、手動復旧を招いた。OSの停止フラグの確認不足が原因。修正で検知機能は改善されたが、復旧時の補助プロセス管理や他プロセスの監視エラーによる検知漏れなど、複数の問題が発覚し対策された。実環境での完全復旧は未検証だ。
ITニュース解説
システムを安定して稼働させる上で、「ウォッチドッグ」と呼ばれるプログラムは非常に重要な役割を担う。このウォッチドッグは、システム内の他のプログラム(アプリケーション)が予期せず停止してしまった際に、その異常を検知し、自動的に復旧させることを目的としている。まるで番犬のようにシステムを監視し、問題が発生すれば即座に対応しようとする存在だ。
しかし、今回あるウォッチドッグが、本来の目的を果たせなかった事例が発生した。企業内で使われているデスクトップアプリケーションが一時的に動作を停止した際、ウォッチドッグはそれを検知できず、結局は人間のエンジニアが手動で復旧作業を行う必要に迫られたのである。アプリケーションの一時停止は、利用者の作業を滞らせるため、ウォッチドッグが自動で解決すべき事態だった。
このウォッチドッグは、OS(オペレーティングシステム)によってアプリケーションが「停止した」状態を検知するよう設計されていた。過去のテストでは、プログラムが完全に停止した場合や、一時的に停止状態に移行して復旧するような基本的なシナリオでは問題なく機能していた。しかし、実際に発生したメモリ不足による問題では、ウォッチドッグはアプリケーションが動いていると判断し続けていたのだ。
一体何が原因だったのか。開発を担当したエンジニアのLatch(ラッチ)は、その原因が「普通のプロセス停止信号」と「リソース不足による一時停止」を同じものとして扱ってしまった点にあると説明する。OSは、アプリケーションの状態を様々な「フラグ」と呼ばれる情報で管理している。フラグとは、例えば「今実行中である」「今停止している」「今メモリが足りなくて一時停止中である」といった、プロセスの状態を示す目印のようなものだ。
今回の問題は、OSが提供する複数のフラグのうち、特に「リソース不足が原因で現在一時停止している」ことを示すフラグ(PROC_FLAG_PA_SUSP)を、ウォッチドッグが読み取っていなかったことにある。ウォッチドッグは単に「停止した状態」を示す一般的なフラグは見ていたが、メモリ不足など特定のシステムリソースが不足したためにOSが強制的にアプリケーションの動作を一時停止させた、という特殊な状況を示すフラグは見落としていたのだ。これにより、アプリケーションは動いていないにもかかわらず、ウォッチドッグからは「停止しているわけではない」と誤って認識されてしまっていた。
この根本的な見落としを修正するため、ウォッチドッグは改良された。まず、アプリケーションの状態を調べるために、外部のプロセス情報取得コマンドを実行するのではなく、OSから直接プロセス情報を読み取るように変更された。これにより、OSが保持するすべてのフラグ、特にリソース不足による一時停止を示すフラグを正確に読み取れるようになった。また、監視自体が何らかの理由で失敗した場合でも、それが正常に監視できなかったことを示す明示的なエラーとして記録し、最後に成功した監視時刻も記録するように改善された。これは、ウォッチドッグ自身が正常に機能しているかを常に確認するための重要な変更点だ。
さらに、この改良版ウォッチドッグに対して、プロダクト批評家のRasp(ラスプ)がさらなる検証を行ったところ、二つの新たな問題点が発見された。
一つ目の問題は、ウォッチドッグが一時停止したアプリケーションを復旧させる際に発生する可能性のあるシナリオに関するものだった。ウォッチドッグが新しいアプリケーションを立ち上げて復旧作業を進めている最中に、古い世代のアプリケーション、あるいは新しいアプリケーションの動作を補助する「ヘルパー」と呼ばれるサブプロセスに対し、誤って終了信号が送られてしまうリスクが見つかったのだ。これは、復旧が完了する前に一部のプロセスが不意に終了させられてしまうことを意味する。
この問題に対処するため、ウォッチドッグはさらに修正された。アプリケーションを終了させるための信号を送る前に、その信号を送る対象のプロセスが、現在復旧を目指している「正しい世代」のアプリケーションの一部であることを、毎回再確認するようになった。単にプロセスの番号だけで判断するのではなく、そのプロセスがいつ作られたか(誕生時刻)、そして他のどのプロセスから起動されたか(親子関係)といった、より詳細な情報を確認することで、誤って関係ないプロセスや古いプロセスの補助機能を終了させてしまう事態を防ぐようになった。
二つ目の問題は、ウォッチドッグがアプリケーションの状態を監視している最中に、システム内の無関係な他のプロセスのメモリ使用状況を読み取ろうとして、それが失敗した場合に起こりうるものだった。この無関係な読み取りの失敗によってエラーが発生すると、ウォッチドッグがその前に正しく検知していたアプリケーションの一時停止状態の情報が、誤って消去されてしまう可能性があったのだ。その結果、ウォッチドッグは一時停止を検知しそこね、復旧作業を開始できなくなる恐れがあった。
この問題に対しても修正が加えられた。ウォッチドッグは、無関係なプロセスのメモリ統計を読み取る前に、監視対象のアプリケーションに関する情報のみを処理するように変更された。これにより、無関係な読み取りエラーが発生しても、それが監視対象アプリケーションの一時停止状態の検知を妨げることがなくなった。もし監視対象のメモリ統計が取得できなくても、それは診断情報として扱われるだけで、一時停止の状態が「リセット」されることはなくなった。ただし、最終的なクリーンアップ処理など、破壊的な操作を行う際には、プロセスの特定に少しでも不確かさがあれば、安全のためにその操作は停止するようになっている。
これらの修正は、Raspによる徹底的な検証によって確認され、ウォッチドッグの信頼性は大きく向上した。しかし、これらのテストはあくまで特定のシナリオにおける振る舞いを検証するためのものであり、実際に大量のメモリが枯渇するような状況下で、アプリケーションの停止を検知し、再起動し、中断された利用者を元の作業に戻すという一連の「完全な復旧」が検証されたわけではない。
今回の出来事について、エンジニアのLatchは、自分が担当するウォッチドッグが自動化すべき復旧作業を、利用者が手動で行わなければならなかったことに対し、自身の責任を認めている。この経験から得られた教訓は、監視プログラムが「何かを監視している」という事実だけでなく、「その監視が実際に何らかの有効な情報を正確に捉えているか」を常に問い続けることの重要性である。システム開発においては、単に「動いている」だけではなく、その「機能が期待通りに、かつ正確に動作しているか」を深く検証し続ける姿勢が不可欠なのだ。