Access non-finalizable objects from finalizer - c#

I want to access object without finalizer from finalizer of other instance.
I know that it is bad idea to access other finalizable object from finalizer because sequence of finalizer call is non-deterministic.
But what about accessing instances without finalizer from finalizer of other objects?
I can not figure out this, the only found in the article http://edn.embarcadero.com/article/29365 :
This means that finalizers should never access other finalizable
objects (objects without finalizers, however, are just fine)
Is any confirmation of this in MSDN?
Currently I want to acquire lock object with variable of type object but I want to be sure that it is ok and object instance is not freed from memory before accessing it.
Thanks

Currently I want to acquire lock object with variable of type object
Accessing that object in your finalizer is fine, nothing happened to it. Actually using it a lock statement, that's not so fine. Blocking the finalizer thread tends to byte badly. It has a time-out at program exit, it must complete and get everything finalized within two seconds. You cannot afford a Monitor.TryEnter() to avoid tripping that timeout, that will be a bad resource leak.
And beware the code smell, you should not be releasing whatever native resource you wrote the finalizer for when other threads can still access it. It is gospel that the finalizer can only run when nobody keeps a reference to the object anymore. Which should also mean that there shouldn't be any point in locking anymore since no thread could have a reference anymore. There is no need to protect shared state with a lock when nobody can read or write it.
Keep in mind that actually writing a finalizer tends to be almost always wrong, native resources should be finalized by their corresponding .NET wrapper class. There are many, the low-level ones are the SafeHandle derived classes.

Objects are not collected till the time they have a root. Assuming the object instance you are talking about is member of the object that is getting finalized, then that object has been alive all the time - because root is f-reachable queue.
However, I will strongly advise against any locking or blocking in finalizer. It could cause ugly deadlocks.

Related

Why does garbage collector process finalizable objects separately?

I am reading Jeffrey Richter's book "CLR via c#". It is quote from there:
Finalize methods are called at the completion of a garbage collection on objects that the GC
has determined to be garbage. This means that the memory for these objects cannot be reclaimed
right away because the Finalize method might execute code that accesses a field.
Because a finalizable object must survive the collection, it gets promoted to another generation, forcing the object
to live much longer than it should
It misled me a little bit. Why cannot finalizable object be reclaimed right away? I cannot understand argument that finalize method might execute code that accesses a field. What is problem? Moreover, I cannot understand why finalizable object should be moved to older generation and stored in separated queue (to be processed in other finalizer thread).
In my opinion the simplest way is to finalize object before removing at all without these additional actions.
Why cannot finalizable object be reclaimed right away? I cannot understand argument that finalize method might execute code that accesses a field. What is problem?
Because Finalize() is just a normal method of the object, so code in it might access any fields of the object.
When garbage collection happens, all threads are frozen.
The two points add up together to the fact that when gc is happening, it cannot execute the Finalize() method right away (All threads are paused during gc!!), while Finalize is expected to be invoked before object being collected.
All these above leads to the fact that garbage collection cannot kill the object immediately before its Finalize() method is invoked. So gc takes the object out from the "death list" (the object is now said to be resurrected), and put it to a queue called "Freachable" ("F" stands for finalization, "reachable" means all objects in it cannot be garbage collected now since gc only collects objects unreachable from roots).
After the gc finished, a special dedicated thread with high priority will take out each entry from the "Freachable" queue and invoke Finalize() method on it, which makes that object finally "garbage collectable", but of course, since the first gc has already ended before this Finalize() calling process, all the objects poped out from "Freachable" can now only be scheduled to next garbage collection.
Moreover, I cannot understand why finalizable object should be moved to older generation and stored in separated queue (to be processed in other finalizer thread).
To understand this, you need to first know the concept of the generation gc model. After objects are popped out from the "Freachable" queue and are again ready for garbage collection, they have been moved to older generation owing to the fact that they survive the previous one.
I think this quote says "finish your unit of work stuff and kill your instance. To kill your instance you should clean up your garbage collection because of your memory."

If an object has been disposed, does suppressing the gc finalizer save it some time?

Garbage Collection can become a time consuming process. In this regard, the GC tends to work only when it has to. If an object has been disposed, to help save time and aid the GC, should the GC's finalizer be suppressed?
using(var sO = new someObject())
{
//work with object
}
public class someObject : IDisposable
{
internal Stream someResource;
internal Context someContext;
public void Dispose()
{
someContext.Dispose();
someResource.Dispose();
//A: does suppressing the GC finalizer here save time for the GC?
//B: can this cause memory leaks?
//GC.SuppressFinalize(this);
}
}
To clear up some confusion:
You only need a finalizer if you need to clean up unmanaged resources in some special way.
If you have no unmanaged resources, then you don't need a finalizer.
If you have a finalizer, then you should definitely implement IDisposable.
If you have a finalizer, then you should call GC.SuppressFinalize in Dispose, because the finalizer doesn't need to be called if you've already cleaned up after yourself.
You only need to call GC.SuppressFinalize if you have a finalizer. If you don't, you probably still want to call it anyway as a defensive measure.
does suppressing the GC finalizer here save time for the GC?
If there are unmanaged resources and your object has a finalizer, then yes; your object might live a long time on the finalization queue if you don't suppress this. The resources you dispose of may also take a long time to finalize (closing an expensive I/O channel, for example).
If you don't have a finalizer, you're saying that you don't have anything unmanaged to clean up. You should still call SuppressFinalize anyway as a defensive measure.
From the FxCop rules:
"Failure to suppress finalization degrades performance and provides no benefits."
For your other question,
can this cause memory leaks?
In this example, yes, if any of the resources are unmanaged. If your object is terminated in some unusual way before it has a chance to invoke Dispose, unmanaged resources won't be properly freed. Consider what happens if someResource is unmanaged and throws an exception while you're using a someObject instance, for example.
If your object holds onto unmanaged resources and you need to guarantee those resources are cleaned up, you need a finalizer too (which would be named ~someObject in your case).
If you actively Dispose an object then yes you should suppress the finalization. There is no need for the object to be finalized if you actively / deterministically release all of the resources. Letting it hang around for the finalizer is just wasting time later on.
One point not yet mentioned: an object need only be considered "live" if there is some execution path via which code might need to access its fields or its object header (a data structure that holds information about the object's type, whether it's been used as a monitor lock, etc.) If an object field holds an unmanaged handle and the last thing the Dispose method does is to close the handle, it's possible that the object may become eligible for finalization while the Dispose method is running. Oops. Not only will the call to GC.SuppressFinalize serve to prevent the finalizer from getting enqueued after it executes; its placement as the last thing Dispose does will prevent the object from becoming eligible for finalization before it executes.

Why does GC put objects in finalization queue?

As I understand, garbage collector in c# will put all objects of a class into finalization queue, as soon as I implement destructor of the class. When I was reading documentation for GC.Suppresfinalize, it mentions that object header already has a bit set for calling finalize.
I am wondering that why the implementers of GC had to put all objects in a queue, and delay the freeup of memory by 1-2 cycles. Could not they just look at the bit flag while releasing memory, then call finalize of the object and then release memory?
No doubt I am an idiot and I not able to understand the working of GC. I am posing this question just to improve my understanding or fill the missing gap in my knowledge
EDIT : If the bit flag is for suppressfinalize, GC implementers could have added another flag in object header for this purpose, no?
So it can run in a different thread and thus keep from blocking the main GC thread.
You can learn a lot about the GC from this MSDN article.
There is a great explanation here
What are the Finalizer Queue and Control+ThreadMethodEntry?
Essentially the reasoning is that it may not always be ideal for the GC to have to wait on finalizer code to execute, so queuing finalizers allows finalization to be deferred until a time when it's more convenient.
It's desirable for garbage collection pauses to be as short as possible. To that end, running finalizers is usually deferred to a later time, when the frantic work of garbage collection is done. It is instead done in the background on a separate thread.
#Jason: this is true for the f-reachable queue. But IMHO it does not explain why there is the finalization-queue itself.
My guess is that the finalization-queue is there to add another information that helps the GC to distinguish between all the possible states of an object life-cycle.
The finalization flag in the object's header says "the object needs to be finalized" or "the object does not need to be finalized" but it does not say if the finalization has already occurred.
But to be honest I don't grasp why it's needed in the current finalization process implementation.
Indeed, here is the naive workflow I imagine possible without the finalization-queue:
when creating the object, if it has a finalizer, the GC sets the finalization flag;
if later SupressFinalize is called then the flag is zeroed;
now let's jump to when the GC collects the object, which is not referenced from anywhere: if the finalization flag is set then the GC puts a reference to the object into the f-reachable queue and lets the finalization thread operates;
later the finalization thread dequeues the reference, resets the finalization flag and runs the finalizer;
if the object wants to be refinalized later it could ReRegisterForFinalize to set the finalization flag again;
later the GC collects the object again: if the finalization flag is not set it knows there is nothing to do and then frees the object memory;
if the finalization flag is set the GC enqueues again a reference to the object into the f-reachable queue and there we go again for another round;
at some point in time the object is happy, completes the finalization and is collected; or the app-domain or process is shutdown and memory is freed anyway.
So seems like in these scenarios there is no need for a finalization-queue, only the finalization flag is useful.
One possible reason would be that from a conceptual point of view there might be a rule like: "an object is collected if and only if it is not referenced from any root".
So not having a finalization queue, and basing the decision to collect an object on the object state itself, checking the finalization flag, is not compatible with this rule.
But really I don't think the GC implementation is based on the dogmatic application of such theoretical rules but only on pragmatic choices; so it's obvious I'm missing some key scenarios where the GC needs the finalization queue to know what to do when collecting an object, but which ones?
The garbage-collector does not identify and examine garbage, except perhaps when processing the Large Object Heap. Instead, its behavior is like a that of a bowling-alley pinsetter removing deadwood between throws: the pinsetter grabs all the pins that are still standing, lifts them off the surface of the lane, and then runs the sweeper bar across the lane without regard for how many pins are on that surface. Sweeping out memory wholesale is much faster than identifying individual objects to be deleted. If 1% of objects have finalizers (the real number's probably even less), then it would be necessary to examine 100 object headers to find each finalizable object. Having a separate list of objects which have finalizers makes it unnecessary for the GC to even look at any garbage objects that don't.

Garbage Collection and Finalizers: Finer Points

In answering another question* on SO, and the subsequent comment discussion, I ran into a wall on a point that I'm not clear on.
Correct me on any point where I'm astray...
When the Garbage Collector collects an object, it calls that object's finalizer, on a separate thread (unless the finalizer has been suppressed, e.g. through a Dispose() method). While collecting, the GC suspends all threads except the thread that triggered the collection (background collection aside).
What isn't clear:
Does the Garbage Collector wait for the finalizer to execute on that object before collecting it?
If not, does it un-suspend threads while the finalizer is still executing?
If it does wait, what happens if the finalizer runs into a lock being held by one of the suspended threads? Does the finalizer thread deadlock? (In my answer, I argue that this is bad design, but I could possibly see cases where this could happen)
* Link to the original question:
.NET GC Accessing a synchronised object from a finalizer
Does the Garbage Collector wait for the finalizer to execute on that object before collecting it?
Your question is a bit ambiguous.
When the GC encounters a "dead" object that needs finalization, it abandons its attempt to reclaim the dead object's storage. Instead, it puts the object on a queue of "objects that I know need finalization" and treats that object as alive until the finalizer thread is done with it.
So, yes, the GC does "wait" until the finalizer is executed before reclaiming the storage. But it does not wait synchronously. It sounds like you're asking "does the GC synchronously call the finalizer right there?" No, it queues up the object to be finalized later and keeps on truckin'. The GC wants to quickly get through the task of releasing garbage and compacting memory so that the program proper can resume running ASAP. It's not going to stop to deal with some whiny object that is demanding attention before it gets cleaned up. It puts that object on a queue and says "be quiet and the finalizer thread will deal with you later."
Later on the GC will check the object again and say "are you still dead? And has your finalizer run?" If the answer is "yes" then the object gets reclaimed. (Remember, a finalizer might make a dead object back into a live one; try to never do that. Nothing pleasant happens as a result.)
Does it un-suspend threads while the finalizer is still executing?
I believe that the GC thaws out the threads that it froze, and signals the finalizer thread "hey, you've got work to do". So when the finalizer thread starts running, the threads that were frozen by the GC are starting up again.
There might have to be unfrozen threads because the finalizer might require a call to be marshalled to a user thread in order to release a thread-affinitized resource. Of course some of those user threads might be blocked or frozen; threads can always be blocked by something.
what happens if the finalizer runs into a lock being held by one of the suspended threads? Does the finalizer thread deadlock?
You betcha. There's nothing magic about the finalizer thread that prevents it from deadlocking. If a user thread is waiting on a lock taken out by the finalizer thread, and the finalizer thread is waiting on a lock taken out by the user thread, then you've got a deadlock.
Examples of finalizer thread deadlocks abound. Here's a good article on one such scenario, with a bunch of links to other scenarios:
http://blogs.microsoft.co.il/blogs/sasha/archive/2010/06/30/sta-objects-and-the-finalizer-thread-tale-of-a-deadlock.aspx
As the article states: finalizers are an extremely complex and dangerous cleanup mechanism and you should avoid them if you possibly can. It is incredibly easy to get a finalizer wrong and very hard to get it right.
Objects that contain a finalizer tend to live longer. When, during a collect, the GC marks an object with a finalizer as being garbage, it will not collect that object (yet). The GC will add that object to the finalizer queue that will run after the GC has finished. Consequence of this is that, because this object is not collected, it moves to the next generation (and with that, all objects it refers to).
The GC suspends all running threads. The finalizer thread on the other hand will run in the background while the application keeps running. The finalizer calls all finalize methods on all objects that are registered for finalization. After the finalizer method on an object has ran, the object will be removed from the queue, and from that point on the object (and possibly all objects it still references) is garbage. The next collection that cleans objects of the generation of that object will (at last) remove that object. Since objects that live in generation 2 are collected about 10 times as less as objects that live in generation 1, and gen 1 ten times as less as gen 0, it can take some time for such object is finally garbage collected.
Because the finalizer thread is just a simple thread that runs managed code (it calls the finalizers), it can block and even dead lock. Because of this it is important to do as little as possible in finalize methods. Because the finalizer is a background thread, a failing finalize method could even bring down the complete AppDomain (yuck!).
You could say that this design is unfortunate, but if you think about it, other designs where the framework cleans our mess effectively, are hard to imagine.
So, to answer your questions:
Yes, only after the object is removed from the finalizer queue, the object will be garbage and the GC will collect it.
The GC suspends all threads, even the finalizer queue.
The finalizer queue can deadlock. Lock as little as possible inside finalize methods.
It's simplest to think of the garbage collector as dividing objects into four groups:
Those which aren't reachable by any rooted object;
Those which are reachable from a list of live finalizable objects, but not from any other rooted object;
Those which are on the list of live finalizable objects, but are also reachable through some rooted object other than that list.
Those which are not on the list of live finalizable objects, but are reachable via some rooted object other than that list.
When the garbage-collector runs, objects of type #1 disappear. Objects of #2 get added to a list of objects needing imminent finalization and removed from the "live finalizable objects" list (thus becoming objects of category #4). Note that the list of objects needing finalization is a normal rooted reference, so objects on this list cannot be collected while they are on it, but if no other rooted reference is created by the time the finalizer is complete the object will move to category #1.

Garbage collection Guarantees

What guarantees are the for the garbage collector?
From my research I have managed to find:
If there is still a reference to the memory it will not be garbage collected
If there is no reference:
When it is GC is non deterministic
When the GC kicks in the finalizer will be run before memory is released.
There is no guarantee about the order of Finalizers (so do not assume parent will be run before child).
But what I really want to know is:
Is there a guarantee that all memory will eventually be garbage collected and the finalizer (destructor) run on the object (assuming the program exited nicely). For example an application with no memory pressure when it eventually exits will it force the GC to go find all objects and make sure the finalizer (destructor) is called (including static member variables)?
I did find a quote on this page:
http://www.c-sharpcorner.com/UploadFile/tkagarwal/MemoryManagementInNet11232005064832AM/MemoryManagementInNet.aspx
In addition, by default, Finalize methods are not called for unreachable objects when an application exits so that the application may terminate quickly.
But I am not sure how authoritative this quote is.
I also found documentation on:
CriticalFinalizerObject
Is there a guarantee that all memory
will eventually be garbage collected
and the finalizer (destructor) run on
the object (assuming the program
exited nicely).
No. From the Object.Finalize documentation it is clear that finalizers may not be invoked if
Some other finalizers don't finish properly:
Another finalizer blocks indefinitely
(goes into an infinite loop, tries to
obtain a lock it can never obtain and
so on). Because the runtime attempts
to run finalizers to completion, other
finalizers might not be called if a
finalizer blocks indefinitely.
Some other finalizers create more
finalizable objects, making it
impossible to finalize all
finalizable objects:
The runtime continues to Finalize
objects during shutdown only while the
number of finalizable objects
continues to decrease.
Some other finalizers throw exceptions:
If Finalize or an override of Finalize
throws an exception, and the runtime
is not hosted by an application that
overrides the default policy, the
runtime terminates the process and no
active try-finally blocks or
finalizers are executed. This behavior
ensures process integrity if the
finalizer cannot free or destroy
resources.
That being said, there are more reasons why you wouldn't want to use finalizers unless strictly necessary.
They slow down the garbage collector
(even making it possible to slow it
down so much that memory is not
reclaimed as fast as it is used up).
They run on another thread, bringing
multi-threading issues into play.
They're not executed in a
deterministic order.
They can resurrect objects which were
already finalized (and which won't be
finalized again unless explicitly
re-registered for finalization).
The only time you should write a finalizer is when you are building a type to handle a new kind of unmanaged resource. For example, a data access layer that uses Sql Server in a business app doesn't need a finalizer anywhere, even though there are unmanaged database connections involved, because the basic SqlConnection class will already finalize those connections if needed. But if you're building a brand new database engine from scratch that has connection limits similar to sql server's and are implementing the ado.net provider for it, that connection type should implement a finalizer to be as sure as possible that your connections are released.
But you don't get any guarantees beyond what happens when a process ends.
Update:
Given this context:
I am having a discussion with a collegue over a code review I did of his code. He insists that the destructor is guranteed to be called on an object. I disagree (but am not sure) and would prefer the use of IDisposable.
You are right to criticize the use of a destructor/finalizer. As I said above, you should only use them when working with an unmanaged resource that is genuinely new. Not just that instance of the resource, but the kind of resource you are working with.
For code that wraps "normal" unmanaged resources (things like SqlConnection, TcpClient, etc), IDisposable is a better choice. Then you know the resource will be cleaned up as soon as Dispose() is called rather than needing to wait for the type to be collected. If no one calls Dispose() (which is likely your colleague's concern), by the time your new type can be collected the instance of the original type for the unmanaged resource you are wrapping should be able to be collected as well, and it's finalizer will release the resource.
The main thing you need to bring to the table is that the finalizer cannot be called until the object is collected. You have to wait on the garbage collector, meaning you may be holding the resource open even longer. IDisposable allows you to release it right away. Of course you could do both, but that doesn't sound like what's going on here, and if you do have both you have to be careful not to conflict with the original type's finalizer or you could cause unwanted and harmful exceptions. And really, your own finalizer implementation is just redundant here and adds needless complexity.
Finally, I have to take issue with this statement:
If there is still a reference to the memory it will not be garbage collected
There can be references to an object and it will still be collected. What matters is if the object is reachable: are any of the references to the object rooted. For example, you may have a list with several objects in it. The list goes out of scope. Obviously there is still a reference to all of the objects in the list, but they can still all be collected in the first pass of the GC because the reference is no longer rooted.
1.6.7.6 of the Spec says:
1.6.7.6 Destructors
A destructor is a member that implements the actions
required to destruct an instance of a
class. Destructors cannot have
parameters, they cannot have
accessibility modifiers, and they
cannot be invoked explicitly. The
destructor for an instance is invoked
automatically during garbage
collection.
The garbage collector is
allowed wide latitude in deciding when
to collect objects and run
destructors. Specifically, the timing
of destructor invocations is not
deterministic, and destructors may be
executed on any thread. For these and
other reasons, classes should
implement destructors only when no
other solutions are feasible.
The
using statement provides a better
approach to object destruction.
So no, it's not guaranteed they are called.
The only time that a finalizer won't be invoked at all is if an AppDomain is forcibly unloaded.
In general, you don't need to worry about it.
There is no guarantee.
There might be a guarantee if your process terminates nicely for some definition of nicely. But there are so many things not nice that can happen:
power failure
process terminated in a 'hard' or 'forced' way
unmanaged thread throwing calling OS exit() function or throwing an exception
call to System.Environment.FailFast, which does:
MSDN: "Terminates a process but does not execute any active try-finally blocks or finalizers."

Categories

Resources