ASP.NET 用デバッガエクステンションが公開されました

こんにちは d99 です。
Tom の blog に記載されているように、psscor2 と呼ばれるデバッガエクステンションが公開となりました。

New debugger extension for .NET, Psscor2, released
https://blogs.msdn.com/tom/archive/2010/03/29/new-debugger-extension-for-net-psscor2-released.aspx

Download Center: Psscor2 Managed-Code Debugging Extension for WinDbg
https://www.microsoft.com/downloads/details.aspx?FamilyID=5c068e9f-ebfe-48a5-8b2f-0ad6ab454ad4&displayLang=en

実はこちらは、主に ASP.NET を担当する弊社エンジニアが使用していたエクステンションになります。遅くなりましたが、やっと公開できる運びとなりました。一般的に使用されている sos.dll のスーパーセットになりますので、是非ご活用頂ければと思います。

今回は、Tess の blog でも紹介されている psscor2 で特長的な二つのコマンドについて、どういったシチュエーションで有効なのかを簡単にご紹介させて頂きます。

New debugger extension for .NET (PSSCOR2)
https://blogs.msdn.com/tess/archive/2010/03/30/new-debugger-extension-for-net-psscor2.aspx

 

!DumpAllExceptions

!DumpAllExceptions は、ダンプファイル中に残されている .NET の例外を列挙するコマンドです。短縮形は !dae です。

例えば、サーバ側で例外が出ているようだ、という時、ハング モード ダンプを採取した上でダンプを開き、エクステンションをロードしてこのコマンドを実行すると、ヒープ中に残っている未処理例外がその時のスタックトレースと共に列挙されます。.NET Framework 2.0 では未処理例外がイベントログに記録されるため有用な状況は限られるかもしれませんが、我々がダンプファイルを拝見する際には一応確認させて頂いているコマンドです。

※ 上記、リンク先のハングモードダンプファイル採取手順と同じ事を行う際には、下記ダウンロードページにて [以前のバージョンの Debugging Tools for Windows] から、バージョン 6.11 をダウンロードして行ってください。

32 ビット版 Debugging Tools for Windows
https://msdn.microsoft.com/ja-jp/windows/hardware/gg463016

列挙される条件は、未処理例外で、かつ、.NET ヒープに例外が残っている必要があります。つまり、 try ~ catch でハンドルしてしまっている場合や、GC.Collect() を実行して .NET ヒープをクリアしてしまった場合などは確認できません。ただ、問題の起きた w3wp.exe プロセスが終了/再起動していない、現象後あまり時間が経ってない、という場合なら 「事後のダンプ採取」 で間に合う事が多いので重宝します。

なお、コマンド結果に ExecutionEngineException、OutOfMemoeryException、StackOverFlowException、などが列挙される場合がありますが、これらの例外は例外が起きてから Exception クラスをインスタンス化するのでは遅いので事前に用意しています。ですので、これらは無視してしまって構いません。

デバッガ(windbg)でのコマンド実行例は以下の通りです(windbg のインストールについては以前の記事をご参照ください)。デバッガと同じフォルダに psscor2 を格納しておけば以下のようになり、Exception.aspx の Button1_Click で 0 除算が起きた事が分かります。

0:027> .load psscor2

0:027> !dae
Going to dump the .NET Exceptions found in the heap.
Loading the heap objects into our cache.
Number of exceptions of this type:        1
Exception MethodTable: 0f26b114
Exception object: 02aafd28
Exception type: System.DivideByZeroException
Message: 0 で除算しようとしました。

InnerException: <none>
StackTrace (generated):
    SP       IP       Function
    020EF354 11521A89 Exception.Button1_Click(System.Object, System.EventArgs)
    020EF35C 66799EC8 System.Web.UI.WebControls.Button.OnClick(System.EventArgs)
    020EF374 66799D2F System.Web.UI.WebControls.Button.RaisePostBackEvent(System.String)
    020EF38C 66799F6B System.Web.UI.WebControls.Button.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(System.String)
    020EF394 66095D9E System.Web.UI.Page.RaisePostBackEvent(System.Web.UI.IPostBackEventHandler, System.String)
    020EF3A0 66095CF5 System.Web.UI.Page.RaisePostBackEvent(System.Collections.Specialized.NameValueCollection)
    020EF3B4 660A7F1E System.Web.UI.Page.ProcessRequestMain(Boolean, Boolean)

以下略。。。

!aspxpages

!aspxpages は、ダンプファイル中に残されている ASP.NET のリクエスト履歴を列挙するコマンドです。

例えば、サーバーから応答が返って来ないようだ、という時、応答が返ってきていない期間中にハングダンプを採取した上でダンプを開き、エクステンションをロードしてこのコマンドを実行すると、どのリクエストを処理中か、もしくは処理が終わっているか、を列挙できます。ハングアップ現象の解析についてはかなり有用なコマンドです。

実際には HttpContext クラスインスタンスを列挙していますので、もし出力に不審点がある場合は同じ事をいくつかのコマンドの組み合わせで確認できます。ただ、コマンド一発で列挙できるのはとても便利ですね。なお、!dae と同じように GC.Collect() で .NET ヒープをクリアしてしまうと表示できない場合があります。

デバッガ(windbg)でのコマンド実行例は以下の通りです。この結果から、TestSite20/Exception.aspx への GET と POST が 「過去に」 行われ、POST については 500 エラーになった事が分かります。上記 !dae と組み合わせれば 500 エラーは 0 除算である事が分かります。なお、実行中のリクエストの場合、Completed が no、Runnning に実行秒数、ThreadId に実行スレッド番号が表示されます。

0:027> .load psscor2
※ 上記 !dae と連続して行う場合は不要です

0:023> !aspxpages
Going to dump the HttpContexts found in the heap.
Loading the heap objects into our cache.
HttpContext    Timeout  Completed     Running  ThreadId ReturnCode   Verb RequestPath+QueryString
0x029ed6f0 19200 Sec yes XXX 200 GET /TestSite20/Exception.aspx
0x02aa2bf4 19200 Sec yes XXX 500 POST /TestSite20/Exception.aspx

Total 2 HttpContext objects

 

今後は他にも有用なコマンドや、もう少し詳細なエクステンションの実行手順をご紹介したいと思います。

ではまた。
d99 でした。