Process Explorer・handle.exe・VMMapによる長期稼働アプリ調査の知識マップ(知識グラフ)
この記事は、装置連携アプリの「だんだん重くなる」「ファイルが消せない」「ハングした」という三大症状を、Process Explorer・handle.exe・VMMapという状態観察系のSysinternalsツールで切り分ける方法を扱う。ファイル使用中はProcess ExplorerのFind Handle or DLLやhandle.exeで掴んでいるプロセスを特定し、ハンドルリークはHandle Countカラムとhandle -sの定点観測で確認でき、GDI/USERオブジェクトの上限接近も同じ手段で監視できる。ハングはThreadsタブのスレッドスタックで調べるが、読むにはdbghelp.dllとシンボルパスからなるシンボル設定が前提になる。Private Bytesの増加はVMMapでHeap・Managed Heap・Private Dataなどに内訳を割ってから専用ツールに進み、プロセス単位で原因が見えないときはRAMMapでOS全体のメモリ使用状況を見る。
Process Explorer
プロセスに読み込まれているDLLだけでなく、ハンドル・スレッドスタック・GDI/USERオブジェクト数なども確認できるSysinternalsのプロセス監視ツール。管理者として実行すると他ユーザーやサービスのプロセスも参照できる。
handle.exe
開いているハンドルの一覧・検索を行う、管理者権限が必要なSysinternalsのコマンドラインツールである。
VMMap
プロセスの仮想・物理メモリを、コミット済み仮想メモリの種類別内訳として分析できるSysinternalsのツールである。
管理者権限
コンピューター全体の設定を変更できる権限。
昇格
ハンドルリーク
参照カウントやハンドルカウントの数え違いなどにより、不要になったハンドル(ファイル・イベント・スレッド・GDIオブジェクト・アクセストークンなどカーネルオブジェクトへの参照)が解放されずに積み上がっていく状態。
GDI/USERオブジェクトの上限
GDIオブジェクト・USERオブジェクトに存在する、プロセスごとの既定上限(既定1万個)とセッション全体の理論上限65,536個という制約である。
シンボルサーバー
PDBなどのシンボルファイルを、ファイル名ではなくバイナリとの一致情報に基づいて整理し、デバッガーが必要なときに取得できるようにする仕組み。
WinDbg
クラッシュダンプやハングしたプロセスの状態をカーネル/ユーザーモードで解析するためのMicrosoft製デバッガー。SOS拡張によるマネージドヒープ解析や、Application Verifierの検出結果の解析にも使われる。
ファイルマッピング(メモリマップトファイル)
ファイルの内容をプロセスやシステムのアドレス空間にマップする仕組み。ディスク上のファイルに裏打ちされる形と、CreateFileMappingにINVALID_HANDLE_VALUEを渡してページファイルに裏打ちされる形(名前付き共有メモリ)がある。Windowsのキャッシュマネージャー自身の実装基盤でもある。
メモリマップトファイル
Private Bytesの増加
プロセスのPrivate Bytesが操作の繰り返しに応じて増え続け、二度と減らない状態である。
メモリリーク(ネイティブ/マネージド)
Private Bytesが増え続ける
RAMMap
OS全体の物理メモリ使用状況を、Use Counts・Processes・File Summaryなどのタブで分析できるSysinternalsのツールである。
使用中ファイルのロック
実行中のexeやロード済みDLLがメモリマップドファイルとしてOSに保持されるため、中身の書き換えと削除がブロックされる状態である。
ファイル使用中
共有違反
ファイル使用中ロック(削除・差し替え不可)
ファイルが使用中
ファイルが削除できない
アプリケーションのハング(応答なし)
ウィンドウが応答なしになり、UIスレッドなどが何らかの待機から戻らない状態である。
ハング
応答なし
ハンドルトレーシング(handle tracing)
ハンドルのopen・close・不正参照の履歴をスタック付きで記録する、Application VerifierのHandlesチェックが有効な際に自動で有効になる機能である。
Sysinternals Live
Sysinternalsツールをダウンロードせずに、live.sysinternals.comのURLやUNCパスから直接実行できるサービスである。
調査目的でのProcess Explorer利用は管理者として実行することが事実上必須で、一般権限では他ユーザーやサービスのプロセスのスタック・ハンドルが見えない(自分と同じユーザーのプロセスだけを見る分には一般権限でもアクセスできる)
handle.exeは公式に管理者権限が必要とされているコマンドラインツールである
VMMapは管理者として実行してから対象プロセスを選ぶ手順になっている(調査目的で他ユーザーやサービスのプロセスを見る場合は事実上必須。自分と同じユーザーのプロセスだけを見る分には一般権限でも動作し得る)
Handle Count・USER Objects・GDI Objects・Private Bytesのカラムを追加し、時間を置いて増え続ける傾きを見ることでハンドルリークを確認できる
handle -s -p <プロセス>による種類別ハンドル数の定期ログで、GUIを開けない環境でもハンドルリークを定点観測できる
USER Objects・GDI Objectsカラムを追加すると、プロセスごとの上限やセッション全体の上限への接近を監視できる
Threadsタブでスレッドスタックの関数名を読むには、Options→Configure SymbolsでDbghelp.dllパスとシンボルパスを設定する必要がある
シンボル解決に使うdbghelp.dllとsymsrv.dllは、Debugging Tools for Windows(WinDbgのインストールに含まれる)のフォルダーから入手する
VMMapのShareable/Mapped File分類で、プロセス間連携などで使われているメモリマップトファイルの領域を確認できる
Private Bytesが増え続ける症状は、VMMapでHeap・Managed Heap・Private Dataなどの分類ごとの内訳を確認することで原因の土俵を特定できる
プロセス単位の疑いをVMMapで確認し、どのプロセスも肥大していなければRAMMapでOS全体の物理メモリ使用状況を見る、という順で進める
ファイルが削除・差し替えできない症状は、Find Handle or DLL(Ctrl+F)でファイル名の部分一致検索をすれば、掴んでいるプロセスを数秒で特定できる
handle.exeにファイル名やパスの一部を渡すと、そのハンドルを開いているプロセスを一覧できる
応答なしのプロセスは、プロパティのThreadsタブでスレッドのスタックを見て、どの関数呼び出しで止まっているかを特定する
.NETアプリのマネージドなハング・デッドロックを正確に追うには、ハング中にダンプを採ってWinDbg+SOSで解析する方が確実
どのコードがハンドルを確保したかまで特定する段階では、Application Verifierのハンドルトレーシングなど専用ツールに進む
Process Explorerはダウンロードして手元で実行するほか、live.sysinternals.comから直接実行することもできる。Sysinternals Liveは入手経路の1つで必須ではない
VMMapはダウンロードして手元で実行するほか、live.sysinternals.comから直接実行することもできる。Sysinternals Liveは入手経路の1つで必須ではない
handle.exeはダウンロードして手元で実行するほか、live.sysinternals.comから直接実行することもできる。Sysinternals Liveは入手経路の1つで必須ではない
RAMMapはダウンロードして手元で実行するほか、live.sysinternals.comから直接実行することもできる。Sysinternals Liveは入手経路の1つで必須ではない