ハングアップ

IIS のサービス自体が突然クラッシュして実行できない場合と異なり、 単に応答が返らなくなる場合があります。応答が遅いか、あるいは、全く反応しないような場合です。 このような状態をハングアップした、と言います。

ハングアップしているときの状態は、次のようなパターンが主なものです。

  1. 何かの処理を待っている
  2. デッドロック状態となり同期オブジェクトの待ちで停止している
    (この場合は待っていても回復しません)
  3. 負荷が高くなり応答が遅い
    通常は予期せぬビジーループ等で CPU 時間を 100% 占有するなどする。(遅いが応答がある)

上記のうち、ここでは処理を待つ場合、あるいはデッドロックしている場合を取り上げます。

この場合は、問題が発生している時点の情報 (ログファイル、IIS 関連プロセスのメモリダンプ) を採取して それを解析することで、原因が特定できる場合が少なくありません。

情報を採取するには Debug Diagnostic Tool を利用するのが最も簡単です。

以下の例は非常に典型的なハングアップ問題に対処する方法です。

実験用の aspx ページ

ここでは、次のページを hang_test.aspx として作成し、ハングアップを模倣します。 このページでは Page_Load にて 120 秒間スレッドをスリープさせています。

<%@ Page Language="C#" %>
<!DOCTYPE html PUBLIC 
"-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
	protected void Page_Load( object sender , EventArgs e ) {

		System.Threading.Thread.Sleep( 120 * 1000 );
		
	}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
<form id="form1" runat="server">
</form>
</body>
</html>

このスクリプトを用いて、ハングアップ時の情報の採取方法及び原因調査方法を示します。

Debug Diagnostic Tool を利用したハングアップ問題の調査と原因究明

Debug Diagnostic Tool を利用して、ハングアップ時の情報を採取する

Debug Diagnostic Tool を起動して、Add Rule... をクリックするとウィザードが開始します。

IIS Hang を選択します。

次の画面でモニターする、URL を入力します。この URL からの応答の有無によって、ハングアップの検出を行います。

サーバーのチェック間隔と、ハングアップが発生した、と検出するまでの待ち時間を指定します。

次の画面で Add Dump Target をクリックして、ダンプを採取するプロセスを指定します。通常は All active IIS/COM+ related processes を指定します。 (ドロップダウンから他の項目を選んでから、再度選びなおすと指定できます)

エントリが追加されました。

ルールの名前を決めます。既存のルールと名前が重なると、どれがどの情報かわかりにくいので、 ユニークな名前を指定してください。

最後に、Activate the rule now (直ちにルールを有効化する) を選択して、Finish をクリックします。

以上で IIS にツールを仕掛けることが出来ました。

ログの採取 ~ 自動採取

Debug Diagnostic Tool がハングアップを検出した場合、その時点の情報 (ログとユーザーダンプ) が採取されます。

この例ではユーザーダンプが 3 個採取されたことがわかります。

ログの解析

Advanced Analysis タブを選択します。

Crash/Hang Analyzers を選択して、Start Analysis をクリックします。

ダンプファイル (*.dmp) を選択します。ファイル名にプロセス名が含まれています。 w3wp.exe でユーザーのプログラムが実行されます。通常は w3wp.exe を確認します。

自動的にダンプが解析されます。

結果は HTML ファイルとして表示されます。

問題はこれをどのように解釈するか、というところです。

解析方法はケース・バイ・ケースで、一言で原因を特定できる場合もあれば、この例のように少し追加調査しないとわからない場合もあります。

ダンプの解析 ~ 簡単な切り分け方法

上記のログの表示から、直ちには問題がわからなかったものの、スレッド 21 には調査する余地があるというメッセージが表示されていたところに着目します。

そこで、自分でユーザダンプを開き、スレッド 21 番を確認してみましょう。

cdb や WinDbg などで、ユーザダンプ (*.dmp) を開きます。この前に、シンボルパスなどは設定しておいてください。

C:\Debuggers>cdb -z "C:\Program Files\DebugDiag\Logs\Hang_Test_Log...

Microsoft (R) Windows Debugger Version 6.10.0003.233 X86
Copyright (c) Microsoft Corporation. All rights reserved.


Loading Dump File [C:\Program Files\DebugDiag\Logs\Hang_Test_Log1\w3wp.exe__D...
User Mini Dump File with Full Memory: Only application data is available

Comment: 'Dump created by Debug Diagnostic Service. IIS_COM+ Hang Dump'
Symbol search path is: srv*C:\websymbols*http://msdl.microsoft.com/download/symbols
Executable search path is:
Windows Server 2008/Windows Vista SP1 Version 6001 (Service Pack 1) MP (2 procs)...
Product: WinNt, suite: SingleUserTS
Machine Name:
Debug session time: Fri Feb 20 14:10:27.000 2009 (GMT-8)
System Uptime: 1 days 16:27:27.614
Process Uptime: 0 days 0:10:24.000
................................................................
................................................................
.......
eax=00000001 ebx=00000001 ecx=7707f6b3 edx=00040002 esi=00000000 edi=00000000
eip=770b9a94 esp=001bf930 ebp=001bf9a0 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!KiFastSystemCallRet:
770b9a94 c3              ret

スレッド 21 番へ移動します。

0:000> ~21s
eax=6fa76914 ebx=00000000 ecx=0001d4c0 edx=02bb2448 esi=0f84e898 edi=00000000
eip=770b9a94 esp=0f84e854 ebp=0f84e8bc iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
ntdll!KiFastSystemCallRet:
770b9a94 c3              ret

スタックバックトレースを確認します。

0:021> kbn 100
 # ChildEBP RetAddr  Args to Child
00 0f84e850 770b83b4 76d6c350 00000001 0f84e898 ntdll!KiFastSystemCallRet
01 0f84e854 76d6c350 00000001 0f84e898 3919cc74 ntdll!NtDelayExecution+0xc
02 0f84e8bc 7104d050 0001d4c0 00000001 39068131 kernel32!SleepEx+0x62
03 0f84e8f0 7112336f 0001d4c0 00000001 0f84e914 mscorwks!EESleepEx+0xbb
04 0f84e900 7112335d 7157dc98 0001d4c0 00000001 mscorwks!CExecutionEngine::ClrSle...
05 0f84e914 7112331c 0001d4c0 00000001 39068091 mscorwks!ClrSleepEx+0x14
06 0f84e950 7112341d 0001d4c0 39068031 02abbb58 mscorwks!Thread::UserSleep+0x63
*** WARNING: Unable to verify checksum for mscorlib.ni.dll
07 0f84e9f0 6fc09225 01ea0c9d 02bb2448 02bb2448 mscorwks!ThreadNative::Sleep+0xce
*** WARNING: Unable to verify checksum for System.Web.RegularExpressions.ni.dll
08 0f84ea04 53c8a7ff 02abbb58 0f84ea28 6c7c2594 mscorlib_ni+0x1d9225
*** WARNING: Unable to verify checksum for System.Web.ni.dll
09 0f84ea10 6c7c2594 02abbb58 02bb2448 02bb2448 System_Web_RegularExpression...
0a 0f84ea28 6c7bba84 02abbb58 02bb2448 02bb2448 System_Web_ni+0x192594
0b 0f84ea40 6c7bbac3 00f82098 02bb2448 02bb2448 System_Web_ni+0x18ba84
0c 0f84ea58 6c7b7b74 00000000 02a901d0 00000000 System_Web_ni+0x18bac3
0d 0f84ebac 6c7b77a4 00000001 02bb2448 00000001 System_Web_ni+0x187b74
0e 0f84ebe4 6c7b76d1 00000001 06a908f4 06a908f4 System_Web_ni+0x1877a4
0f 0f84ec20 6c7b7666 02bb2448 0f84ec40 6c7b7642 System_Web_ni+0x1876d1
10 0f84ec2c 6c7b7642 00000000 02bb2448 02abb438 System_Web_ni+0x187666
11 0f84ec50 6c7bdb16 0f0d7390 00000000 06ae73fc System_Web_ni+0x187642
12 0f84ec84 6c79132c 00000000 00000000 00000000 System_Web_ni+0x18db16
13 0f84ecc0 6cd8524f 0f84ed20 3e260ed9 7103a6b8 System_Web_ni+0x16132c
14 0f84ed54 6cd7b674 00000000 00000000 0f84ed78 System_Web_ni+0x75524f
15 0f84ed68 6cd660cd 06a9a01c 3e260ed9 7103a6b8 System_Web_ni+0x74b674
16 0f84edd4 6ce3a692 06ae73fc 3e260ed9 7103a6b8 System_Web_ni+0x7360cd
17 0f84ee54 6ce3a47f 00000000 0000000a 00000000 System_Web_ni+0x80a692
...
36 0f84f858 7709e4b6 0f0bdc88 7032df35 00000000 kernel32!BaseThreadInitThunk+0xe
37 0f84f898 7709e489 71151fcf 0f0bdc88 00000000 ntdll!__RtlUserThreadStart+0x23
38 0f84f8b0 00000000 71151fcf 0f0bdc88 00000000 ntdll!_RtlUserThreadStart+0x1b

System_Web_ni などは、このスレッドでマネージドスタックが形成されているときに見られます。

そこで、sos デバッガエクステンションを用いて、マネージドスタックを確認します。

0:021> !sos.clrstack
OS Thread Id: 0x1630 (21)
ESP       EIP
0f84e9a4 770b9a94 [HelperMethodFrame: 0f84e9a4] System.Threading.Thread.Sleep...
0f84e9f8 6fc09225 System.Threading.Thread.Sleep(Int32)
0f84e9fc 01ea0c9d ASP.hang_test_aspx.Page_Load(System.Object, System.EventArgs)
0f84ea10 53c8a7ff System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr, Sys...
 System.Object, System.EventArgs)
0f84ea20 6c7c2594 System.Web.Util.CalliEventHandlerDelegateProxy.Callback(
System.Object, System.EventArgs)
0f84ea34 6c7bba84 System.Web.UI.Control.OnLoad(System.EventArgs)
0f84ea48 6c7bbac3 System.Web.UI.Control.LoadRecursive()
0f84ea60 6c7b7b74 System.Web.UI.Page.ProcessRequestMain(Boolean, Boolean)
0f84ebb8 6c7b77a4 System.Web.UI.Page.ProcessRequest(Boolean, Boolean)
0f84ebf0 6c7b76d1 System.Web.UI.Page.ProcessRequest()
0f84ec28 6c7b7666 System.Web.UI.Page.ProcessRequestWithNoAssert(System.Web.HttpC...
0f84ec34 6c7b7642 System.Web.UI.Page.ProcessRequest(System.Web.HttpContext)
0f84ec48 01ea07fe ASP.hang_test_aspx.ProcessRequest(System.Web.HttpContext)
...
0f84f4cc 00af22b4 [ContextTransitionFrame: 0f84f4cc]
0:021> ?0001d4c0
Evaluate expression: 120000 = 0001d4c0

上記から、このスレッドでは hang_test.asp の Page_Load にて、System.Threading.Thread.Sleep を呼び出していることが浮かび上がってきました。 確かにこれは、テスト用のページで行っていた処理そのものです。

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 Web/DB プログラミング徹底解説