﻿<?xml version="1.0" encoding="utf-8"?><rss version="2.0"><channel><title>Ayende @ Rahien</title><link>http://ayende.com</link><description>Ayende @ Rahien</description><copyright>Copyright (C) Ayende Rahien  2004 - 2021 (c) 2026</copyright><ttl>60</ttl><item><title>Michael Morton commented on More information of GC issue</title><description>@Alois: 
  
HttpRuntime.ShutdownAppDomain() is the result of a long code path starting in System.Web.HostingEnvironment.InitiateShutdown().  When WebDev server exits it calls Microsoft.VisualStudio.WebHost.Server.Stop() which in turn calls Microsoft.VisualStudio.WebHost.Host.Shutdown().  WebHost.Host.Shutdown() does exactly one thing; call HostingEnvirionment.InitiateShutdown().
  
  
I would expect other hosts, including IIS, to behave similarily with regards to the HostingEnvironment.
  
  
Another interesting piece of information is that not one, but two threads are spawned to handle the shutdown.  HostingEnvironment.InitiateShutdownInternal() queues a work item to the thread pool which in turn calls the rest of it.
</description><link>http://ayende.com/3825/more-information-of-gc-issue#comment14</link><guid>http://ayende.com/3825/more-information-of-gc-issue#comment14</guid><pubDate>Fri, 23 Jan 2009 07:38:12 GMT</pubDate></item><item><title>Ayende Rahien commented on More information of GC issue</title><description>Alois,
  
The fact that a finalizer was called while a strong reference is being held to the object was a good indication, I believe.
</description><link>http://ayende.com/3825/more-information-of-gc-issue#comment13</link><guid>http://ayende.com/3825/more-information-of-gc-issue#comment13</guid><pubDate>Fri, 23 Jan 2009 07:03:51 GMT</pubDate></item><item><title>Alois Kraus commented on More information of GC issue</title><description>Hi Ayende,
  
  
yes I am aware of that. The reflector code shows the HttRuntime. From your call stack and the HttpRuntime code snipped I can deduce that no AppDomain Unload has happened yet. At least not in this thread. So the question remains in which thread did you find an AppDomain Unload? If none then I suspect that it is a simple Dispose issue
  
  
Dispose()
  
{
  
    myObject.Dispose();
  
    myObject = null;  // GC can kick in and call finalizers on all objects which are contained by myObject.
  
}
  
  
Yours,
  
   Alois Kraus
  
</description><link>http://ayende.com/3825/more-information-of-gc-issue#comment12</link><guid>http://ayende.com/3825/more-information-of-gc-issue#comment12</guid><pubDate>Fri, 23 Jan 2009 07:02:03 GMT</pubDate></item><item><title>Ayende Rahien commented on More information of GC issue</title><description>Stephen,
  
See Michael's post about what is actually happening.
</description><link>http://ayende.com/3825/more-information-of-gc-issue#comment11</link><guid>http://ayende.com/3825/more-information-of-gc-issue#comment11</guid><pubDate>Fri, 23 Jan 2009 00:34:28 GMT</pubDate></item><item><title>Ayende Rahien commented on More information of GC issue</title><description>Alois,
  
The problem happens specifically with ASP.Net, not with console app.
</description><link>http://ayende.com/3825/more-information-of-gc-issue#comment10</link><guid>http://ayende.com/3825/more-information-of-gc-issue#comment10</guid><pubDate>Fri, 23 Jan 2009 00:32:43 GMT</pubDate></item><item><title>Stephen commented on More information of GC issue</title><description>Well, you can store things in the HttpApplicationState, this basically represents the 'top level' single instance of the web app.. although its actually initialized by the first HttpApplication..
  
  
As I was saying before, there isn't a single HttpApplication instance in a 'web application', because HttpApplication is what 'runs' requests.. since a server can be running multiple requests at a time, there can be multiple of these running.. this is where the 'Application' property of the HttpApplication (Global / global.asax) comes in - because it returns a single HttpAppliataionState that all HttpApplication's share.. of course you'll need to do locking around this object (but it provides locking for you).
</description><link>http://ayende.com/3825/more-information-of-gc-issue#comment9</link><guid>http://ayende.com/3825/more-information-of-gc-issue#comment9</guid><pubDate>Thu, 22 Jan 2009 23:56:44 GMT</pubDate></item><item><title>Michael Morton commented on More information of GC issue</title><description>I did some digging around with reflector...
  
  
Make note of that in HttpRuntime.Init():
  
this._appDomainUnloadallback = new WaitCallback(this.ReleaseResourcesAndUnloadAppDomain);
  
  
Then the shutdown code path:
  
HttpRuntime.ShutdownAppDomain()
  
... calls ...
  
ThreadPool.QueueUserWorkItem(_theRuntime._appDomainUnloadallback); &lt;-- new thread here
  
... calls ...
  
HttpRuntime.Dispose()
  
... which eventually fires Application_End.
  
  
This call path matches your stack trace and does explain why it can happen concurrently.
</description><link>http://ayende.com/3825/more-information-of-gc-issue#comment8</link><guid>http://ayende.com/3825/more-information-of-gc-issue#comment8</guid><pubDate>Thu, 22 Jan 2009 23:50:58 GMT</pubDate></item><item><title>Alois Kraus commented on More information of GC issue</title><description>Hi Ayende,
  
  
your call stack of HttApplication does not indicate a concurrent AppDomain unload and application end. 
  
  
private void ReleaseResourcesAndUnloadAppDomain(object state)
  
{
  
...
  
     try
  
    {
  
        this.Dispose();
  
    }
  
    catch
  
    {
  
    }
  
    Thread.Sleep(250);
  
    AddAppDomainTraceMessage("before Unload");
  
    AppDomain.Unload(Thread.GetDomain());
  
...
  
}
  
  
That behaviour does look fine to me.  The problem seems to come from the fact that after/during dispose of your objects some object graphs become unrooted and thus eligible for garbage collection.
  
  
What do you expect from this program:
  
    class SomeData
  
    {
  
        public SomeData()
  
        {
  
            Console.WriteLine("SomeData created");
  
        }
  
  
        ~SomeData()
  
        {
  
            Console.WriteLine("SomeData finalized");
  
        }
  
    }
  
  
    class Program
  
    {
  
        static void DoSomethingWithData()
  
        {
  
            var list = new List
&lt;somedata()
  
            {
  
                new SomeData(),
  
                new SomeData()
  
            };
  
        }
  
  
        static void Main(string[] args)
  
        {
  
            DoSomethingWithData();
  
            GC.Collect();
  
            GC.WaitForPendingFinalizers();
  
            Console.ReadLine();
  
        }
  
    }
  
  
Yes the list does reference the SomeData objects but the output is:
  
SomeData created
  
SomeData created
  
SomeData finalized
  
SomeData finalized
  
  
I think your problem is related to the disposal of your root application object which allows GC to shoot down the rest of your objects. You could try to hide the relevant data in a class with statics to force your objects to be rooted. 
  
  
public class KeepAliveData
  
{
  
   public static AppObject GlobalAppObject;
  
}
  
  
That should help to force the GC to keep your application object alive. As a side note you should not do too much in your finalizers. The release of unmanaged resources (interop handles) is the only thing that is more or less safe all other things like taking locks will introduce its own set of problems.
  
  
Yours,
  
  Alois Kraus
  
  
  
&gt;</description><link>http://ayende.com/3825/more-information-of-gc-issue#comment7</link><guid>http://ayende.com/3825/more-information-of-gc-issue#comment7</guid><pubDate>Thu, 22 Jan 2009 23:02:35 GMT</pubDate></item><item><title>Ayende Rahien commented on More information of GC issue</title><description>Michael,
  
This is supposed to be where I am cleaning my resources for the application.
  
It is _not_ supposed to be a race condition to see who wins, my disposal code or the finalizers
</description><link>http://ayende.com/3825/more-information-of-gc-issue#comment6</link><guid>http://ayende.com/3825/more-information-of-gc-issue#comment6</guid><pubDate>Thu, 22 Jan 2009 21:54:01 GMT</pubDate></item><item><title>Michael Morton commented on More information of GC issue</title><description>@Ayende: The only guarantee that the statement regarding Application_End makes is that it will be called once.  It makes no promises on how it will be called or what else will be going on during that call.
  
</description><link>http://ayende.com/3825/more-information-of-gc-issue#comment5</link><guid>http://ayende.com/3825/more-information-of-gc-issue#comment5</guid><pubDate>Thu, 22 Jan 2009 21:23:40 GMT</pubDate></item><item><title>Torbj&amp;#246;rn Gyllebring commented on More information of GC issue</title><description>I've struggled with a diffrent but also quite odd problem relating to how Application_Event's are called. It's quite possible to get an Authenticate event *before* Start. 
  
  
Really strange thins seems to be abound when it comes to startup/shutdown is handled. 
</description><link>http://ayende.com/3825/more-information-of-gc-issue#comment4</link><guid>http://ayende.com/3825/more-information-of-gc-issue#comment4</guid><pubDate>Thu, 22 Jan 2009 21:00:54 GMT</pubDate></item><item><title>Ayende Rahien commented on More information of GC issue</title><description>Bruno,
  
sigh
  
That is not the problem.
  
The problem is concurrent execution of the finalizer and the application_end, which cleans up resources.
</description><link>http://ayende.com/3825/more-information-of-gc-issue#comment3</link><guid>http://ayende.com/3825/more-information-of-gc-issue#comment3</guid><pubDate>Thu, 22 Jan 2009 19:04:25 GMT</pubDate></item><item><title>Bruno Mart&amp;#237;nez commented on More information of GC issue</title><description>Finalizers run in a dedicated thread (several threads in the future), so the concurrent execution may be expected.
</description><link>http://ayende.com/3825/more-information-of-gc-issue#comment2</link><guid>http://ayende.com/3825/more-information-of-gc-issue#comment2</guid><pubDate>Thu, 22 Jan 2009 19:00:30 GMT</pubDate></item><item><title>Stephen commented on More information of GC issue</title><description>Well, the application_end sub is called when the HttpApplication is unloaded, ASP.NET pools HttpApplication instances and uses them to forefill requests.. when the pool is recycled (which happens after a timeout) all the HttpApplications will end.. but also, .NET can create additional HttpApplication's if non are available in the pool, once they try to return to the pool - if its 'full' they instead get 'disposed' of..
  
  
This has always been my understanding, theres quite a lot of 'funky' threading that can happen, like when an application isn't read to forefill the request, its first created and initialized on the request thread before being transfered to the processing threads.. I guess all these things can attribute to a somewhat confusing api.
</description><link>http://ayende.com/3825/more-information-of-gc-issue#comment1</link><guid>http://ayende.com/3825/more-information-of-gc-issue#comment1</guid><pubDate>Thu, 22 Jan 2009 16:10:52 GMT</pubDate></item></channel></rss>