NOTE: The following steps apply to ASP.NET 4.0 (64 bit). They have not been tested in other versions of ASP.NET.
(For ASP.NET 2.0 32 bit, please refer to http://blogs.msdn.com/b/asiatech/archive/2011/07/06/how-to-troubleshoot-httpexception-request-timed-out-asp-net-2-0-32-bit.aspx )
Symptoms
========
The user may receive the following response intermittently:
Request timed out.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. Exception Details: System.Web.HttpException: Request timed out.Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[HttpException (0x80004005): Request timed out.]
The following warning may occur in application event logs:
Log Name: Application
Source: ASP.NET 4.0.30319.0
Event ID: 1309
Task Category: Web Event
Level: Warning
Keywords: Classic
User: N/A
Description:
Event code: 3001
Event message: The request has been aborted.
…
Application information:
Process information:
Process name: w3wp.exe
Account name: IIS APPPOOL\ASP.NET v4.0
Exception information:
Exception type: HttpException
Exception message: Request timed out.
Request information:
This kind of issue is typically occurs when the ASP.NET request executes for a period of time longer than the maximum timeout period allowed for server-side code execution.
This maximum timeout period can be set by executionTimeout attribute of httpRuntime element in config file. (The default value is 110 seconds in .Net 4.0)
How to reproduce
===============
Create an ASPX page named as sleep.aspx. It will sleep for 20 seconds:
<%@ Page Language="C#" %>
<%@ import Namespace="System.Diagnostics" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
DateTime time = DateTime.Now;
Response.Write(String.Format("Time: {0}:{1}:{2}", time.Hour, time.Minute, time.Second) +
"\tCurrent process: " + Process.GetCurrentProcess().Id.ToString());
Response.Write("<BR>");
Response.Write(String.Format("This application is running in {0}", System.Environment.Version.ToString()));
System.Threading.Thread.Sleep(20000);
}
</script>
<html>
<head>
<title>ASP.NET Simple Page</title>
</head>
<body bgcolor="#FFFFFF">
<p><asp:label id="Message" runat="server" /></p>
</body>
</html>
Create a web.config and put it in the same folder as sleep.aspx. It sets the maximum timeout period to 5 seconds.
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.web>
<httpRuntime executionTimeout="5"/>
</system.web>
</configuration>
Use your browser to access sleep.aspx and you will receive “[HttpException (0x80004005): Request timed out.]” error message after a while. The corresponded warning will also appear in application event log.
NOTE:
You may notice that this “[HttpException (0x80004005): Request timed out.]” error message may not immediately appear in 5 seconds. Internally ASP.NET uses a Timer (an instance of System.Threading.Timer) to invoke the request cancelation process. This timer is fired once every 15 seconds. Therefore in reality the request can timeout at any time between 5 seconds and 20 seconds.
Please refer to http://blogs.msdn.com/b/pedram/archive/2007/10/02/how-the-execution-timeout-is-managed-in-asp-net.aspx
How to Troubleshoot
You can create a Debug Diagnostic 1.2 Performance rule to capture the dump files for the long running requests.
In this article I will introduce the steps to capture the dump file while “[HttpException (0x80004005): Request timed out.]” error occurs.
The typical *mistake* people may make is to configure a debugger to monitor HttpException and generate dump files while HttpException occurs.
In fact ASP.NET will throw ThreadAbortException when the request times out although it shows HttpException to the users.
It is not practicable to generate dump files for all ThreadAbortException. To troubleshoot this issue we have to set a breakpoint just before the ThreadAbortException is thrown. (Use ILSpy to check the code)
To set the breakpoint, we have to find out the offset address of the above breakpoint. (This offset may vary for different version of system.web.dll)
We can use Windbg shipped in Debugging Tools for Windows to attach to w3wp.exe (or open a hang dump file which was collected on that machine). Run the following commands:
0:040> .loadby sos clr
0:040> !name2ee system.web.dll System.Web.RequestTimeoutManager+RequestTimeoutEntry.TimeoutIfNeeded
Module: 000007fed56f1000
Assembly: System.Web.dll
Token: 0000000006002423
MethodDesc: 000007fed57bd248
Name: System.Web.RequestTimeoutManager+RequestTimeoutEntry.TimeoutIfNeeded(System.DateTime)
JITTED Code Address: 000007fed599b220
We can get the JITTED code address. Then disassembly the method and identify the breakpoint we need to set (highlighted):
0:040> !U 000007fed599b220
preJIT generated code
System.Web.RequestTimeoutManager+RequestTimeoutEntry.TimeoutIfNeeded(System.DateTime)
Begin 000007fed599b220, size 28. Cold region begin 000007fed6467e30, size 36
Hot region:
>>> 000007fe`d599b220 53 push rbx
000007fe`d599b221 57 push rdi
000007fe`d599b222 4883ec28 sub rsp,28h
000007fe`d599b226 488bd9 mov rbx,rcx
000007fe`d599b229 488b4b20 mov rcx,qword ptr [rbx+20h]
000007fe`d599b22d 803900 cmp byte ptr [rcx],0
000007fe`d599b230 e8db13f3ff call System.Web.HttpContext.MustTimeout(System.DateTime) (000007fe`d58cc610)
000007fe`d599b235 488bf8 mov rdi,rax
000007fe`d599b238 4885ff test rdi,rdi
000007fe`d599b23b 0f85efcbac00 jne System_Web_ni!System.Web.RequestTimeoutManager+RequestTimeoutEntry.TimeoutIfNeeded(System.DateTime)+0xaccc10 (000007fe`d6467e30)
000007fe`d599b241 4883c428 add rsp,28h
000007fe`d599b245 5f pop rdi
000007fe`d599b246 5b pop rbx
000007fe`d599b247 c3 ret
At first we want to set the breakpoint at the address 000007fe`d6467e30. However this address may vary in different process.
Therefore we choose the address 000007fe`d599b23b which has a static offset 1b from the method System.Web.RequestTimeoutManager+RequestTimeoutEntry.TimeoutIfNeeded(System.DateTime). But we only need to generate the dump file when the value of the register rdi is not null according to the following instruction:
Save the following text as aspnet_timeout.cfg and put it under c:\.
<ADPlus Version='2'>
<!-- Configuring ADPlus to log all first chance exceptions -->
<!-- Will still create full dump for any type of second chance exceptions -->
<KeyWords>
<keyword Name="loadbysos"> .loadby sos clr</keyword>
<keyword Name="GetJIT"> !name2ee System.web.dll System.Web.RequestTimeoutManager+RequestTimeoutEntry.TimeoutIfNeeded </keyword>
<keyword Name="JITAddress"> .foreach /pS 0n13 ( record {!name2ee System.web.dll System.Web.RequestTimeoutManager+RequestTimeoutEntry.TimeoutIfNeeded}) { r $t1= ${record}; bp $t1+0x1b ".if @rdi {.dump /ma /u ${AdpDumpDirEsc}\\Full Request timed out ${AdpProcName}_.dmp;g} .else {g}"; .printf"*breakpoint list*\n"; bl} </keyword>
</KeyWords>
<Settings>
<Option> NoDumpOnFirst </Option>
<RunMode> CRASH </RunMode>
</Settings>
<PreCommands>
<DebugActions> loadbysos; GetJIT; JITAddress </DebugActions>
</PreCommands>
</ADPlus>
Open a command prompt with *elevated administrator privileges* and change the current directory to the folder where Debugging Tools for Windows is installed (The default location is %programfiles%\Debugging Tools for Windows (x64)
Run the command:
%windir%\system32\inetsrv\appcmd list wp
You will get the PID of the worker process for the problematic application pool.
Then run the following command:
adplus.exe -c c:\aspnet_timeout.cfg -o <output folder> -p <pid of problematic apppool>
Where <output foder> is the existing folder where you want to save the dump files
There will be one cdb.exe window popped up. Please keep this window running because it is monitoring the problematic application pool. If “Request timed out” occurs, it will automatically generate the dump files.
How to find out which operation causes “Request timed out” from dump files
=======================================================
Use windbg to open the dump file. Then load sos
0:036> .loadby sos clr
Dump all objects in the stack of the current thread. You will find System.Threading.Thread object:
0:036> !dso
OS Thread Id: 0x824 (36)
RSP/REG Object Name
rax 00000000ffbbd030 System.Threading.Thread
rbx 00000000ffbc42a8 System.Web.RequestTimeoutManager+RequestTimeoutEntry
rcx 00000000ffbbd700 System.Web.HttpContext
rsi 000000013fd14660 System.Web.RequestTimeoutManager
rdi 00000000ffbbd030 System.Threading.Thread
r12 00000000ffbb7630 System.Collections.ArrayList
0000000005B6E660 00000000ffbbd700 System.Web.HttpContext
0000000005B6E6C8 000000013fd14900 System.Web.Util.DoubleLinkList
0000000005B6E6D8 00000000ffbb7630 System.Collections.ArrayList
0000000005B6E708 00000000ffbb0248 System.Threading.ContextCallback
0000000005B6E710 000000013fd149b0 System.Threading._TimerCallback
0000000005B6E720 000000013fd14660 System.Web.RequestTimeoutManager
0000000005B6E730 000000013fd14660 System.Web.RequestTimeoutManager
0000000005B6E758 00000000ffbb0248 System.Threading.ContextCallback
0000000005B6E760 00000000ffbb75e8 System.Threading.ExecutionContext
0000000005B6E7C0 000000013fd149b0 System.Threading._TimerCallback
0000000005B6E7D0 000000013fd149b0 System.Threading._TimerCallback
0000000005B6E800 00000000ffbb75e8 System.Threading.ExecutionContext
0000000005B6E830 000000013fd149b0 System.Threading._TimerCallback
0000000005B6E848 000000013fd10e28 System.Threading.TimerBase
0000000005B6E9B8 00000000ffbb74d8 System.Collections.Hashtable+HashtableEnumerator
0000000005B6EA90 000000013fd149b0 System.Threading._TimerCallback
0000000005B6EA98 000000013fd149b0 System.Threading._TimerCallback
0000000005B6EB08 00000000ffbb00b0 System.Threading.ContextCallback
0000000005B6EB90 000000013fbca9f8 System.Threading._TimerCallback
Dump the information of System.Threading.Thread object and you will find the field DONT_USE_InternalThread:
0:036> !do 00000000ffbbd030
Name: System.Threading.Thread
MethodTable: 000007fef6e87208
EEClass: 000007fef6a0f050
Size: 88(0x58) bytes
File: C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
Fields:
MT Field Offset Type VT Attr Value Name
000007fef6ed5bb0 400079a 8 ....Contexts.Context 0 instance 000000013fcb4758 m_Context
000007fef6ea9a28 400079b 10 ....ExecutionContext 0 instance 00000000ffbbe1b8 m_ExecutionContext
000007fef6e86738 400079c 18 System.String 0 instance 0000000000000000 m_Name
000007fef6e86f78 400079d 20 System.Delegate 0 instance 0000000000000000 m_Delegate
000007fef6e93c20 400079e 28 ...ation.CultureInfo 0 instance 0000000000000000 m_CurrentCulture
000007fef6e93c20 400079f 30 ...ation.CultureInfo 0 instance 0000000000000000 m_CurrentUICulture
000007fef6e85890 40007a0 38 System.Object 0 instance 0000000000000000 m_ThreadStartArg
000007fef6e93318 40007a1 40 System.IntPtr 1 instance 250e430 DONT_USE_InternalThread
000007fef6e8c620 40007a2 48 System.Int32 1 instance 2 m_Priority
000007fef6e8c620 40007a3 4c System.Int32 1 instance 10 m_ManagedThreadId
000007fef6eb6330 40007a4 318 ...LocalDataStoreMgr 0 shared static s_LocalDataStoreMgr
>> Domain:Value 000000000241e680:NotInit 00000000024d19c0:NotInit <<
000007fef6eaf4f8 40007a5 10 ...alDataStoreHolder 0 shared TLstatic s_LocalDataStore
>> Thread:Value <<
Run !threads command to list all threads and you will find the corresponded thread (whose OS thread Id is dd4) which causes “Request timed out”:
0:036> !threads
ThreadCount: 18
UnstartedThread: 0
BackgroundThread: 17
PendingThread: 0
DeadThread: 1
Hosted Runtime: no
PreEmptive Lock
ID OSID ThreadOBJ State GC GC Alloc Context Domain Count APT Exception
13 1 1158 000000000244d810 8220 Enabled 000000013fed0fb0:000000013fed1040 000000000241e680 0 Ukn
27 2 1e4 000000000246dc80 b220 Enabled 0000000000000000:0000000000000000 000000000241e680 0 MTA (Finalizer)
29 3 570 00000000024c10a0 100a220 Enabled 0000000000000000:0000000000000000 000000000241e680 0 MTA (Threadpool Worker)
30 4 1694 00000000024d2620 1220 Enabled 0000000000000000:0000000000000000 000000000241e680 0 Ukn
31 7 1b54 000000000251c460 8009220 Enabled 0000000000000000:0000000000000000 000000000241e680 0 MTA (Threadpool Completion Port)
17 6 d3c 0000000002515900 8008220 Enabled 0000000000000000:0000000000000000 000000000241e680 0 MTA (Threadpool Completion Port)
32 8 1574 0000000002523660 1009220 Enabled 000000017fc89968:000000017fc8afd0 000000000241e680 0 MTA (Threadpool Worker)
XXXX 9 000000000257b150 1019820 Enabled 0000000000000000:0000000000000000 000000000241e680 0 MTA (Threadpool Worker)
33 5 1428 000000000259b620 1009220 Enabled 00000000ffbb3910:00000000ffbb4fd0 000000000241e680 0 MTA (Threadpool Worker)
34 a 1108 000000000250e430 3009220 Enabled 000000015fbbbbc8:000000015fbbcfd0 00000000024d19c0 1 MTA (Threadpool Worker)
35 b 374 0000000002589260 1009220 Enabled 00000000ffbb5650:00000000ffbb6fd0 000000000241e680 0 MTA (Threadpool Worker)
36 c 824 00000000025603d0 1009220 Disabled 00000000ffbb7820:00000000ffbb8fd0 00000000024d19c0 0 MTA (Threadpool Worker)
37 d 14ac 000000000147e170 1009220 Enabled 00000000ffbb97b0:00000000ffbbafd0 000000000241e680 0 MTA (Threadpool Worker)
38 e 928 000000000147e880 1009220 Enabled 00000000ffbbb238:00000000ffbbcfd0 000000000241e680 0 MTA (Threadpool Worker)
5 f 1abc 0000000002412080 220 Enabled 00000000ffbb1988:00000000ffbb2fd0 000000000241e680 0 Ukn
39 10 1118 0000000002413b90 1009220 Enabled 00000000ffbc1478:00000000ffbc2fd0 000000000241e680 0 MTA (Threadpool Worker)
2 11 1a34 0000000001480a40 220 Enabled 00000000ffbbf158:00000000ffbc0fd0 000000000241e680 0 Ukn
40 12 1870 00000000025a0e60 1009220 Enabled 0000000000000000:0000000000000000 000000000241e680 0 MTA (Threadpool Worker)
Switch to the problematic thread and list the call stack. You will find the sleep function:
0:036> ~~[1108]s
ntdll!NtDelayExecution+0xa:
00000000`7720165a c3 ret
0:034> !clrstack
OS Thread Id: 0x1108 (34)
Child SP IP Call Site
00000000059cdf48 000000007720165a [HelperMethodFrame: 00000000059cdf48] System.Threading.Thread.SleepInternal(Int32)
00000000059ce070 000007ff001d064a ASP.sleep_aspx.Page_Load(System.Object, System.EventArgs)
00000000059ce0e0 000007fee1499c09 System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr, System.Object, System.Object, System.EventArgs)
00000000059ce110 000007fedf018f57 System.Web.UI.Control.LoadRecursive()
00000000059ce160 000007fedf014a78 System.Web.UI.Page.ProcessRequestMain(Boolean, Boolean)
00000000059ce230 000007fedf013d51 System.Web.UI.Page.ProcessRequest(Boolean, Boolean)
00000000059ce2a0 000007fedf013bfd System.Web.UI.Page.ProcessRequest()
00000000059ce330 000007fedf0129f7 System.Web.UI.Page.ProcessRequest(System.Web.HttpContext)
00000000059ce380 000007fedf01c4e1 System.Web.HttpApplication+CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
00000000059ce460 000007fedefe8f1e System.Web.HttpApplication.ExecuteStep(IExecutionStep, Boolean ByRef)
00000000059ce530 000007fedf779915 System.Web.HttpApplication+PipelineStepManager.ResumeSteps(System.Exception)
00000000059ce5f0 000007fedf6a7455 System.Web.HttpApplication.BeginProcessRequestNotification(System.Web.HttpContext, System.AsyncCallback)
00000000059ce640 000007fedf687c76 System.Web.HttpRuntime.ProcessRequestNotificationPrivate(System.Web.Hosting.IIS7WorkerRequest, System.Web.HttpContext)
00000000059ce6e0 000007fedf76b0af System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr, IntPtr, IntPtr, Int32)
00000000059ce880 000007fedf76b962 System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr, IntPtr, IntPtr, Int32)
00000000059ce8d0 000007fedf7699e1 DomainNeutralILStubClass.IL_STUB_ReversePInvoke(Int64, Int64, Int64, Int32)
00000000059cf188 000007fef7f09c97 [NDirectMethodFrameStandalone: 00000000059cf188] System.Web.Hosting.UnsafeIISMethods.MgdIndicateCompletion(IntPtr, System.Web.RequestNotificationStatus ByRef)
00000000059cf150 000007fedf71c467 DomainNeutralILStubClass.IL_STUB_PInvoke(IntPtr, System.Web.RequestNotificationStatus ByRef)
00000000059cf220 000007fedf76b1e4 System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr, IntPtr, IntPtr, Int32)
00000000059cf3c0 000007fedf76b962 System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr, IntPtr, IntPtr, Int32)
00000000059cf410 000007fedf7699e1 DomainNeutralILStubClass.IL_STUB_ReversePInvoke(Int64, Int64, Int64, Int32)
00000000059cf678 000007fef7f09efb [ContextTransitionFrame: 00000000059cf678]
Regards,
Xin Jin From APGC DSI Team
Hi,
Thank you so much for writing this article! It's really great.
I'm having one small issue. When I run windb as you show, i get the following output
0:089> !name2ee system.web.dll
Module: 000007fee81a1000
MethodDesc: 000007fee826d330
JITTED Code Address: 000007fee844b4c0
0:089> !U 000007fee844b4c0
Begin 000007fee844b4c0, size 28. Cold region begin 000007fee8f18c30, size 36
*** WARNING: Unable to verify checksum for C:\Windows\assembly\NativeImages_v4.0.30319_64\System.Web\be472c4f636fc5b8fc38476dbfe01358\System.Web.ni.dll
*** ERROR: Module load completed but symbols could not be loaded for C:\Windows\assembly\NativeImages_v4.0.30319_64\System.Web\be472c4f636fc5b8fc38476dbfe01358\System.Web.ni.dll
>>> 000007fe`e844b4c0 53 push rbx
000007fe`e844b4c1 57 push rdi
000007fe`e844b4c2 4883ec28 sub rsp,28h
000007fe`e844b4c6 488bd9 mov rbx,rcx
000007fe`e844b4c9 488b4b20 mov rcx,qword ptr [rbx+20h]
000007fe`e844b4cd 803900 cmp byte ptr [rcx],0
000007fe`e844b4d0 e81b11f3ff call System_Web_ni+0x1dc5f0 (000007fe`e837c5f0) (System.Web.HttpContext.MustTimeout(System.DateTime), mdToken: 0000000006001ce1)
000007fe`e844b4d5 488bf8 mov rdi,rax
000007fe`e844b4d8 4885ff test rdi,rdi
000007fe`e844b4db 0f854fd7ac00 jne System_Web_ni+0xd78c30 (000007fe`e8f18c30)
000007fe`e844b4e1 4883c428 add rsp,28h
000007fe`e844b4e5 5f pop rdi
000007fe`e844b4e6 5b pop rbx
000007fe`e844b4e7 c3 ret
So I put 0xd78c30 in my cfg file but, I'm not catching the HTTP Timeout exceptions after start ADPlus. ADPlus runs and logs successfully, but I'm not getting dumps when the HTTP Timeout Exception occurs.
Any ideas about what I might be doing wrong? Anything to try?
Thanks!
Richard
Hi Richard,
You can try to set the symbol path by running the command .symfix in windbg.
regards,
Xin Jin
0:037> .symfix
0:037> .loadby sos clr
0:037> !name2ee system.web.dll System.Web.RequestTimeoutManager+RequestTimeoutEntry.TimeoutIfNeeded
Module: 59201000
Token: 0600699b
MethodDesc: 592926e4
JITTED Code Address: 593f4200
0:037> !U 593f4200
Begin 593f4200, size 29. Cold region begin 59d14150, size 23
>>> 593f4200 55 push ebp
593f4201 8bec mov ebp,esp
593f4203 57 push edi
593f4204 56 push esi
593f4205 8bf1 mov esi,ecx
593f4207 8b4e10 mov ecx,dword ptr [esi+10h]
593f420a 8d4508 lea eax,[ebp+8]
593f420d ff7004 push dword ptr [eax+4]
593f4210 ff30 push dword ptr [eax]
593f4212 3909 cmp dword ptr [ecx],ecx
593f4214 e85f83f5ff call System_Web_ni+0x14c578 (5934c578) (System.Web.HttpContext.MustTimeout(System.DateTime), mdToken: 060025f7)
593f4219 8bf8 mov edi,eax
593f421b 85ff test edi,edi
593f421d 0f852dff9100 jne System_Web_ni+0xb14150 (59d14150)
593f4223 5e pop esi
593f4224 5f pop edi
593f4225 5d pop ebp
593f4226 c20800 ret 8
Cold region:
59d14150 8bce mov ecx,esi
59d14152 e849bb6cff call System_Web_ni+0x1dfca0 (593dfca0) (System.Web.RequestTimeoutManager+RequestTimeoutEntry.RemoveFromList(), mdToken: 0600699a)
59d14157 b9508f4859 mov ecx,offset System_Web_ni+0x288f50 (59488f50) (MT: System.Web.HttpApplication+CancelModuleException)
59d1415c e8ef4c63ff call System_Web_ni+0x148e50 (59348e50) (System_Web_ni)
59d14161 8bd0 mov edx,eax
59d14163 c6420401 mov byte ptr [edx+4],1
59d14167 8bcf mov ecx,edi
59d14169 e89a0963ff call System_Web_ni+0x144b08 (59344b08) (System_Web_ni)
59d1416e e9b0006eff jmp System_Web_ni+0x1f4223 (593f4223)
In your sample you had:
From this trace which address gets put in the config file & why ?
Thanks for the comments. I have updated this article.