4

Just out of curiosity I was wondering if there is a possibility of a scenario when garbage collector fails to run or doesn't run at all (possibly due to an exception) ?

If yes, most probably there would be an OutOfMemory/ Stackoverflow exception . Then in that case just by looking at the exception message, stacktrace etc can we identify the core issue of gc failing to run.

Soner Gönül
  • 97,193
  • 102
  • 206
  • 364
Nitin
  • 298
  • 4
  • 14
  • You could attach a Memory Profiler and see what's happening. – jordanhill123 Mar 06 '13 at 13:15
  • This looks like a question for someone who knows the ins and outs of .NET thoroughly. – Freeman Mar 06 '13 at 13:24
  • I don't think this is something you have to worry about. The GC does not run managed code and when it fails, your whole AppDomain probably goes down with it. The GC runs fine btw in case of an OOM; it doesn't locate any memory itself, just shuffles it around. It's hard to imagine a stackoverflow preventing the GC to run properly. – Steven Mar 06 '13 at 13:26
  • Raymond Chen [wrote about this](http://blogs.msdn.com/b/oldnewthing/archive/2010/08/09/10047586.aspx). He eventually concludes, "A correctly-written program cannot assume that finalizers will ever run," but the discussion leading up to that point is excellent. – Brian Mar 07 '13 at 21:51

4 Answers4

5

As others have mentioned, numerous things can prevent the GC from running. FailFast fails fast; it doesn't stop to take out the trash before the building is demolished. But you asked specifically about exceptions.

An uncaught exception produces implementation-defined behaviour, so it is implementation-defined whether finally blocks run, whether garbage collection runs, and whether the finalizer queue objects are finalized when there is an uncaught exception. An implementation of the CLR is permitted to do anything when that happens, and "anything" includes both "run the GC" and "do not run the GC". And in fact implementations of the CLR have changed their behaviour over time; in v1.0 of the CLR an uncaught exception on the finalizer thread took out the process, in v2.0 an uncaught exception on the finalizer thread is caught, the error is logged, and finalizers keep on running.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
2

There are four questions of interest:

  • Can something cause the program to die entirely, without the garbage-collector getting a chance to run

  • Can something prevent the garbage-collector from running without causing the system to die entirely

  • Can something prevent objects' finalizers from running without causing the system to die entirely

  • Can an exception make an object uncollectable for an arbitrary period of time

With regard to the first one, the answer is "definitely". There are so many ways that could potentially happen, that there's no need to list them here.

With regard to the second question, the answer is "generally no", since failure of the garbage collector would cripple a program; there may be some cases, however, in which portions of a program which do not use GC-managed memory may be able to keep running even though the portions that use managed objects could be blocked indefinitely.

With regard to the third question, it used to be in .net that an exception in a finalizer could interfere with the action of other finalizers without killing the entire application; such behavior has been changed since .net 2.0 so that uncaught exceptions thrown from finalizers will usually kill the whole program. It is possible, however, that an exception which is thrown and caught within a poorly-written finalizer might result in its failing to clean up everything it was supposed to, leading to question #4.

With regard to the fourth question, it is quite common for objects to establish long-lived (possibly static) references to themselves when they are created, and for them to destroy such references as part of clean-up code. If an exception prevents that clean-up code from running as expected, it may cause the objects to become uncollectable even if they are no longer useful.

supercat
  • 77,689
  • 9
  • 166
  • 211
0

yes, in Java there used to be the situation where the program could stop without the GC being run for the last time - in most cases this is OK as all the memory is cleared up when the program's heap is destroyed, but you can have the problem of objects not having their finalisers being run, this may or may not be a problem for you, depending what those finalisers would do.

I doubt you'll be able to determine the GC failure, as the program will be as dead as a parrot, in a non-clean manner, so you probably won't even get a stacktrace. You might be able to post-mortem debug it (if you've turned on the right dbg settings, .NET is sh*te when it comes to working nicely with the excellent Windows debugging tools).

gbjbaanb
  • 51,617
  • 12
  • 104
  • 148
0

There are certain edge cases where a finally block will not execute - calling FailFast is one case, and see the question here for others.

Given this, I would imagine there are cases (especially in using statements / IDisposable objects) where the resource cleanup/garbage collection occurring in a finally block are not executed.

More explicitly, something like this:

try
{
    //new up an expensive object, maybe one that uses native resources
    Environment.FailFast(string.Empty);
}
finally
{
    Console.WriteLine("never executed");
}
Community
  • 1
  • 1
goric
  • 11,491
  • 7
  • 53
  • 69