<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Todd's Blog : ASP.NET Debugging</title><link>http://blogs.msdn.com/toddca/archive/tags/ASP.NET+Debugging/default.aspx</link><description>Tags: ASP.NET Debugging</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Event Handlers Gone Wild</title><link>http://blogs.msdn.com/toddca/archive/2006/09/05/event-handlers-gone-wild.aspx</link><pubDate>Wed, 06 Sep 2006 00:10:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:741667</guid><dc:creator>Toddca</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/toddca/comments/741667.aspx</comments><wfw:commentRss>http://blogs.msdn.com/toddca/commentrss.aspx?PostID=741667</wfw:commentRss><description>Today I ran across an issue that my good buddy &lt;A href="http://blogs.msdn.com/tess/" mce_href="http://blogs.msdn.com/tess/"&gt;Tess&lt;/A&gt; hit with one of her &lt;A href="http://blogs.msdn.com/tess/archive/2006/01/23/516139.aspx" mce_href="http://blogs.msdn.com/tess/archive/2006/01/23/516139.aspx"&gt;customers&lt;/A&gt;&amp;nbsp;a while back.&lt;BR&gt;&lt;BR&gt;The application in question here is an ASP.NET web application that is exhibiting fairly high memory usage after almost a day of usage (approx 400-500 MB). Just as in Tess's case the number of event handlers was really high as you can see from this snip of the !dumpheap -stat command:&lt;BR&gt;&lt;BR&gt;
&lt;TABLE class="" style="WIDTH: 448px; HEIGHT: 92px; BACKGROUND-COLOR: silver"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&lt;FONT size=2&gt;MD,Count,Size,Name&lt;BR&gt;=====================================&lt;BR&gt;&lt;/FONT&gt;&lt;FONT size=2&gt;0x024cd82c &lt;FONT color=#ff0000&gt;876,697 24,547,516 System.ResolveEventHandler&lt;/FONT&gt;&lt;BR&gt;0x019e4300 156,448 29,216,964 System.String&lt;BR&gt;0x000cf740 238 66,842,468 Free&lt;BR&gt;Total 1,464,956 objects, Total size: 182,475,044&lt;/FONT&gt; &lt;BR&gt;&lt;BR&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;EM&gt;Note that when working managed high memory issues I always start with !dumpheap -stat to get the landscape.&lt;/EM&gt;&lt;BR&gt;&lt;BR&gt;The customer stated that they were registering for the AppDomain's &lt;A href="http://msdn2.microsoft.com/en-us/library/system.appdomain.assemblyresolve.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/system.appdomain.assemblyresolve.aspx"&gt;AssemblyResolve&lt;/A&gt; event in the global.asax and provided the code that showed what they were doing. Now the code below is incorrect and we will get back to that in a bit however&amp;nbsp;even being&amp;nbsp;wrong&amp;nbsp;it still could not account for over 867,000 event handlers being added to AppDomain's event.&lt;BR&gt;&lt;BR&gt;
&lt;TABLE class="" style="WIDTH: 500px; HEIGHT: 100px; BACKGROUND-COLOR: silver"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;public&lt;/FONT&gt; HttpApplication() : &lt;FONT color=#0000ff&gt;base&lt;/FONT&gt;() {&lt;BR&gt;&amp;nbsp; AppDomain.CurrentDomain.AssemblyResolve += &lt;FONT color=#0000ff&gt;new&lt;/FONT&gt; ResolveEventHandler(MyAssemblyResolver.ResolveAssembly);&lt;BR&gt;}&lt;/FONT&gt; &lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;So given the time the application had been up (approx 21hrs) there must be some common code that is getting called to register for these events elsewhere. I found the code in a class they use to derive all of their WebForm classes from; a custom BasePage class. Of course we are having them remove that code and that should get them back in much better shape.&lt;BR&gt;&lt;BR&gt;Now how do we fix the global.asax code. Well the problem here is that a new HttpApplication is created each time one is needed by a web application and this means you could have more than one handler registered.&amp;nbsp;Now if you have a really low volume site you will only ever see one of these in most cases, however as your traffic gets heavier additional HttpApplications will be spun up to handle the concurrent requests. Think of the number of HttpApplication objects as your high watermark for the number of concurrent requests your site has seen.&lt;BR&gt;&lt;BR&gt;So the fix is to only register for this event handler once and doing this through a static constructor of the HttpApplication would probably be the best approach (though not the only). Since the CLR ensures that static constructors are only called once per AppDomain this will ensure we do not register for the handler multiple times.&lt;BR&gt;&lt;BR&gt;
&lt;TABLE class="" style="WIDTH: 500px; HEIGHT: 111px; BACKGROUND-COLOR: silver"&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD class=""&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;static&lt;/FONT&gt; HttpApplication()&amp;nbsp;{ &amp;nbsp; &lt;BR&gt;&amp;nbsp; AppDomain.CurrentDomain.AssemblyResolve += &lt;FONT color=#0000ff&gt;new&lt;/FONT&gt; ResolveEventHandler(MyAssemblyResolver.ResolveAssembly); &lt;BR&gt;}&lt;/FONT&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=741667" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/toddca/archive/tags/ASP.NET+Debugging/default.aspx">ASP.NET Debugging</category><category domain="http://blogs.msdn.com/toddca/archive/tags/General+.Net+Framework/default.aspx">General .Net Framework</category></item><item><title>AppPool Running ASP.NET 2.0 May Crash On Process Exit</title><link>http://blogs.msdn.com/toddca/archive/2006/03/01/apppool-running-asp-net-2-0-may-crash-on-process-exit.aspx</link><pubDate>Wed, 01 Mar 2006 19:43:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:541368</guid><dc:creator>Toddca</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/toddca/comments/541368.aspx</comments><wfw:commentRss>http://blogs.msdn.com/toddca/commentrss.aspx?PostID=541368</wfw:commentRss><description>&lt;P&gt;&lt;FONT face=Verdana size=2&gt;Ran into an interesting issue the other day while working with a customer and I thought I would share what we learned.&lt;BR&gt;&lt;BR&gt;&lt;STRONG&gt;Problem&lt;/STRONG&gt;&lt;BR&gt;Customer's IIS AppPool running on Windows Server 2003 SP1 with ASP.NET 2.0 RTM installed would crash anytime the&amp;nbsp;AppPool would shutdown.&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;&lt;STRONG&gt;Debugging&lt;BR&gt;&lt;/STRONG&gt;I received a user mode dump file of the crashing process and found the following stack:&lt;/FONT&gt;&lt;/P&gt;&lt;FONT size=2&gt;
&lt;P&gt;&lt;FONT face=Garamond color=#000000&gt;0:024&amp;gt; kb&lt;BR&gt;ChildEBP RetAddr Args to Child&lt;BR&gt;0125fd18 6a2a2fef 01892710 800703e3 00000000 0x64006f&lt;BR&gt;0125fd30 79f2f3b0 000003e3 00000000 01894090 webengine!CorThreadPoolCompletionCallback+0x35 0125fd94 79ecb00b 00000000 00000000 80a78be3 mscorwks!ThreadpoolMgr::intermediateThreadProc+0x49&lt;BR&gt;0125fd98 00000000 00000000 80a78be3 00000008 mscorwks!ThreadpoolMgr::intermediateThreadProc+0x49&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Garamond color=#000000 size=2&gt;
&lt;P&gt;0:024&amp;gt; r&lt;BR&gt;eax=800703e3 ebx=00000001 ecx=01892710 edx=01894090 esi=01892fd0 edi=000003e3&lt;BR&gt;eip=0064006f esp=0125fd1c ebp=000b9790 iopl=0 nv up ei ng nz na pe nc&lt;BR&gt;cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010282&lt;BR&gt;0064006f ?? ???&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;Obviously eip is totally bogus here and hence the crash.&lt;BR&gt;&lt;BR&gt;ASP.NET uses Threadpool completion callbacks for a number of things including File change notification callbacks and performance counters.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;Looking at the stack I found an &lt;FONT size=2&gt;ERROR_OPERATION_ABORTED error 3 DWORDs down.&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;FONT face=Verdana size=2&gt;&lt;FONT size=2&gt;&lt;FONT face=Garamond size=2&gt;
&lt;P&gt;0:024&amp;gt; dd esp&lt;BR&gt;0125fd1c 6a2a2fef 01892710 &lt;FONT color=#ff0000&gt;800703e3&lt;/FONT&gt; 00000000&lt;BR&gt;0125fd2c 01894090 00000000 79f2f3b0 000003e3&lt;BR&gt;0125fd3c 00000000 01894090 09feda8b 00000000&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Garamond size=2&gt;
&lt;P&gt;&lt;FONT face=Verdana&gt;Looking a little bit further down the stack I found the OVERLAPPED_COMPLETION structure which is returning that it was canceled. Not surprising since we are shutting down.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;0:024&amp;gt; dt OVERLAPPED_COMPLETION 01894090&lt;BR&gt;+0x000 Internal : 0xc0000120 &lt;FONT color=#008000&gt;STATUS_CANCELLED -&amp;gt; The I/O request was canceled.&lt;/FONT&gt;&lt;BR&gt;+0x004 InternalHigh : 0&lt;BR&gt;+0x008 Offset : 0&lt;BR&gt;+0x00c OffsetHigh : 0&lt;BR&gt;+0x008 Pointer : (null)&lt;BR&gt;+0x010 hEvent : (null)&lt;BR&gt;+0x014 pCompletion : 0x01892710 ICompletion&lt;/P&gt;&lt;/FONT&gt;&lt;FONT face=Verdana size=2&gt;&lt;FONT size=2&gt;
&lt;P&gt;When we take a look at the ICompletion interface we can see our EIP 4 DWORDS within the VTable. So maybe&amp;nbsp;we should not be trying to call our callback when the status is STATUS_CANCELLED but this should be legal. So we still do not know why&amp;nbsp;we are getting this status in the first place.&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Garamond&gt;0:024&amp;gt; dt 0x01892710 ICompletion&lt;BR&gt;+0x000 __VFN_table : 0x01892fd0&lt;BR&gt;0:024&amp;gt; dd 0x01892fd0 l4&lt;BR&gt;01892fd0 01893078 00700070 0043005f &lt;FONT color=#ff0000&gt;0064006f&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;this is our EIP&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;/FONT&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;The next step in the investigation was to try to ascertain what this callback was originally for. This was a bit of a fishing expedition in that I needed to try to account for all the IO Completion calls. Fortunately my customer was able to allow me access to his machine so I could debug this live or this would have been really hard to track down. I eventually narrowed it down to the performance counter callback. The performance counter block was NULL and this indicated a problem in initializing the performance counters. A bit of live debugging narrowed the problem down to a permissions problem accessing the registry at HKLM\CurrentControlSet\Services\ASP.NET_2.0.50727\Names. This registry key (along with others) are ACLed in such a way that only a small set of users/groups are allowed to access and write to that key.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;&lt;STRONG&gt;Solution&lt;/STRONG&gt;&lt;BR&gt;The problem we found was that the NETWORK_SERIVCE account which was running the AppPool was not a member of the IIS_WPG group which is required to access and read the performance registry key. Adding the NETWORK_SERVICE to this group resolved the issue.&amp;nbsp;&lt;/FONT&gt;&lt;FONT face=Verdana size=2&gt;Needless to say we are tracking this issue and will correct it.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Verdana size=2&gt;&lt;STRONG&gt;&lt;FONT style="BACKGROUND-COLOR: #ffffff" color=#ff0000&gt;Update&lt;/FONT&gt;&lt;/STRONG&gt;&lt;BR&gt;We now have an official KB on this one: &lt;A href="http://support.microsoft.com/Default.aspx?scid=kb;en-us;918041&amp;amp;spid=8940&amp;amp;sid=513" mce_href="http://support.microsoft.com/Default.aspx?scid=kb;en-us;918041&amp;amp;spid=8940&amp;amp;sid=513"&gt;http://support.microsoft.com/Default.aspx?scid=kb;en-us;918041&amp;amp;spid=8940&amp;amp;sid=513&lt;/A&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=541368" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/toddca/archive/tags/ASP.NET+Debugging/default.aspx">ASP.NET Debugging</category></item></channel></rss>