Debug.Assert in ASP.NET Application

Posted by Hugh Ang at 3/14/2008 04:31:00 PM

My most recent project was an ASP.NET 2.0 application developed in Visual Studio 2005. During the first build and deployment into dev integration environment, everything went pretty well except for one page. Request for this page was just hanging. I started to investigate and I captured a hang dump using adplus. In windbg, I found out the longest running thread. Suspecting that is the thread that was hanging, I looked at its CLR stack:

0:001> !clrstack
* Symbols can not be loaded because symbol path is not initialized. *
* *
* The Symbol Path can be set by: *
* using the _NT_SYMBOL_PATH environment variable. *
* using the -y argument when starting the debugger. *
* using .sympath and .sympath+ *
PDB symbol for mscorwks.dll not loaded
OS Thread Id: 0x2fac (1)
006bf414 77f88a77 [NDirectMethodFrameStandalone: 006bf414] Microsoft.Win32.SafeNativeMethods.MessageBox(System.Runtime.InteropServices.HandleRef, System.String, System.String, Int32)
006bf430 7a4f839a System.Diagnostics.AssertWrapper.ShowMessageBoxAssert(System.String, System.String, System.String)
006bf460 7a4fabb2 System.Diagnostics.DefaultTraceListener.Fail(System.String, System.String)
006bf4a0 7a4faad7 System.Diagnostics.DefaultTraceListener.Fail(System.String)
006bf4a4 7a500a22 System.Diagnostics.TraceInternal.Fail(System.String)
006bf4e0 7a6e2523 System.Diagnostics.TraceInternal.Assert(Boolean, System.String)
006bf4e4 7a4fa6cb System.Diagnostics.Debug.Assert(Boolean, System.String)
006bf4e8 1ae8b7c9 CondosPaymentPageBase.GetResidentData()
006bf528 1ae8b567 CondosPaymentPageBase.OnLoad(System.EventArgs)
006bf534 66143ad0 System.Web.UI.Control.LoadRecursive()
006bf548 66155106 System.Web.UI.Page.ProcessRequestMain(Boolean, Boolean)
006bf700 66154a1b System.Web.UI.Page.ProcessRequest(Boolean, Boolean)
006bf738 66154967 System.Web.UI.Page.ProcessRequest()
006bf770 66154887 System.Web.UI.Page.ProcessRequestWithNoAssert(System.Web.HttpContext)
006bf778 6615481a System.Web.UI.Page.ProcessRequest(System.Web.HttpContext)
006bf78c 1bb8ccae ASP.payment_3_history_aspx.ProcessRequest(System.Web.HttpContext)
006bf798 65ff27d4 System.Web.HttpApplication+CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
006bf7cc 65fc15b5 System.Web.HttpApplication.ExecuteStep(IExecutionStep, Boolean ByRef)
006bf80c 65fd32e0 System.Web.HttpApplication+ApplicationStepManager.ResumeSteps(System.Exception)
006bf85c 65fc0225 System.Web.HttpApplication.System.Web.IHttpAsyncHandler.BeginProcessRequest(System.Web.HttpContext, System.AsyncCallback, System.Object)
006bf878 65fc550b System.Web.HttpRuntime.ProcessRequestInternal(System.Web.HttpWorkerRequest)
006bf8ac 65fc5212 System.Web.HttpRuntime.ProcessRequestNoDemand(System.Web.HttpWorkerRequest)
006bf8b8 65fc3587 System.Web.Hosting.ISAPIRuntime.ProcessRequest(IntPtr, Int32)
006bfa68 79f35ee8 [ContextTransitionFrame: 006bfa68]
006bfab8 79f35ee8 [GCFrame: 006bfab8]
006bfc10 79f35ee8 [ComMethodFrame: 006bfc10]

And the native stack looked like this:

0:001> kb
ChildEBP RetAddr Args to Child
006bf1b0 77e4f9f0 50000018 00000003 00000003 NTDLL!ZwRaiseHardError+0xb
006bf20c 77e34398 00d3b684 00d3c298 00040212 USER32!ServiceMessageBox+0x16b
006bf35c 77e339cb 006bf36c 006bfa68 00000028 USER32!MessageBoxWorker+0x10a
006bf3b4 77e4fa54 00000000 00d3b684 00d3c298 USER32!MessageBoxExW+0x77
*** WARNING: Unable to verify checksum for
006bf43c 7a4fad1d 00000000 00d1c4fc 00d28944 USER32!MessageBoxW+0x49
006bf454 7a4fabb2 00000000 00d24bf8 04cfda28 System_ni+0xbad1d
006bf494 7a4faad7 00000000 7a500a22 00000000 System_ni+0xbabb2
006bf4d8 7a6e2523 7a4fa6cb 1ae8b7c9 00d113c0 System_ni+0xbaad7
00000000 00000000 00000000 00000000 00000000 System_ni+0x2a2523

At this point, it was clear to me that some data condition in dev int environment had caused Debug.Assert to fail. The assert failure message box was waiting to be closed. But on an IIS box with the ASP worker process running in the context of a service account, this UI interaction is simply not going to work.

As you may know, Debug.Assert will be left out of the IL code by compilers for release build. Our MSBuild script that produced the deployment package did have the "release" switch turned on. So what went wrong? It turned out that the web deployment project we had, "Generate debug information" option was checked. I initially thought this would give me pdb files. But obviously this meant a debug build, irrespective of the "Configuration=Release" setting for the MSBuild script.