none
Mechanics of WaitForPendingFinalizers RRS feed

  • Question

  • Does WaitForPendingFinalizers wait for the internal queue to become empty OR wait until the last finalizable object's finalizer has completed?

    Testing here suggests it is the former - I called Collect then WaitForPendingFinalizers then Collect again and managed to trap a thread under debug a call by the GC thread to a cleanup function AFTER all of these three previous calls!.

    Is there any way to ENSURE that all finalizers - that are going to be called - have in fact been called and returned from that call?

    This is for a shared memory application - we do NOT want any thread including GC thread to access the shared region once weve begun to stop a service.

    The service stop handler does the call to WaitForPendingFinalizers and then exits, I'm seeing a GC call to a Finalizer take place AFTER WaitForPendingFinalizers has been called...

    Thanks

    Cap'n

    Saturday, May 5, 2012 6:45 PM

Answers

  • Hi, 

    What happens when you create an object?

    while GC's allocator , after allocating the memory for an object, sees the object is finalizable adds the reference to finalizable queue. Later when GC finds the object is dead and GC.SuppressFinalize is not called on object , adds to "F-reachable queue" (ready for finalization) and set an event for finalization thread to run. 

    After GC is done it's work manged threads starts, since finalization thread is also managed thread with high priority sees there are finalizable objects in queue to be executed and starts executing.

    Is there any way to ENSURE that all finalizers - that are going to be called - have in fact been called and returned from that call?

    All finalizers will get called for sure , unless you have finalization method and suppress by calling GC.SuppressFinalize.

    "Does WaitForPendingFinalizers wait for the internal queue to become empty OR wait until the last finalizable object's finalizer has completed?"

    Call on GC.WaitForPendingFinalizers, waits till F-reachable queue become empty. 

    The service stop handler does the call to WaitForPendingFinalizers and then exits, I'm seeing a GC call to a Finalizer take place AFTER WaitForPendingFinalizers has been called...

    When managed threads are resumed after GC, since finalization thread is with high priority starts cleaining and  Worker threads (with same priority) also runs at same time. with WaitForPendingFinalizers(), worker threads will wait till finalization thread completes.

     It's better practice finalizer should be used only to free up unmanaged code and shouldn't be long.

     I hope this helps you..


    If this post answers your question, please click "Mark As Answer". If this post is helpful please click "Mark as Helpful".


    Sunday, May 6, 2012 5:22 AM
  • Hi Cap'n

    Does WaitForPendingFinalizers wait for the internal queue to become empty OR wait until the last finalizable object's finalizer has completed?

    Both. WaitForPendingFinalizers suspends the thread on which it is called and waits for the thread that is processing the freachable queue to empty the queue. This is however normally done *after* each object's Finalize method has been called on the high-priority finalization thread.

    I called Collect then WaitForPendingFinalizers then Collect again and managed to trap a thread under debug a call by the GC thread to a cleanup function AFTER all of these three previous calls!

    Working under the debugger prolonges the lifetime of objects, so this is not a good indicative.

    Is there any way to ENSURE that all finalizers - that are going to be called - have in fact been called and returned from that call?

    No. Under circumstances a certain finalizer may enter an endless loop in which case the other finalizers will not execute. Finalizers are not destructors. Their code might in fact not even have been jitted when the finalization queue gets to them. Furthermore, under low memory conditions, the CLR might not be able to compile the finalizer's code. This means your application could leak unmanaged ressource.  So, no quarantees at all.

    You *could* derive your class from System.Runtime.ConstrainedExecution.CriticalFinalizerObject to guarantee finalization for a particular object under normal conditions. The CLR does the jitting upon constructing the type, so the finalizer bits are readily available. But what if the finalizer referes to a type from another assembly, that is not available at finalization time? - The only thing we know for sure is that *if* a CriticalFinalizerObject gets finalized, it does so after all other non-critical finalizers have been called. But if the process does not exit gracefully (e.g. Task-Manager shutdown) not even this quarantee holds true. Finalizers can also be aborted when internal timing tresholds are exceeded.

    Summing it all up: Don't make assumptions about the sequence or timing of finalization.

    Marcel

    Sunday, May 6, 2012 8:03 AM

All replies

  • Hi, 

    What happens when you create an object?

    while GC's allocator , after allocating the memory for an object, sees the object is finalizable adds the reference to finalizable queue. Later when GC finds the object is dead and GC.SuppressFinalize is not called on object , adds to "F-reachable queue" (ready for finalization) and set an event for finalization thread to run. 

    After GC is done it's work manged threads starts, since finalization thread is also managed thread with high priority sees there are finalizable objects in queue to be executed and starts executing.

    Is there any way to ENSURE that all finalizers - that are going to be called - have in fact been called and returned from that call?

    All finalizers will get called for sure , unless you have finalization method and suppress by calling GC.SuppressFinalize.

    "Does WaitForPendingFinalizers wait for the internal queue to become empty OR wait until the last finalizable object's finalizer has completed?"

    Call on GC.WaitForPendingFinalizers, waits till F-reachable queue become empty. 

    The service stop handler does the call to WaitForPendingFinalizers and then exits, I'm seeing a GC call to a Finalizer take place AFTER WaitForPendingFinalizers has been called...

    When managed threads are resumed after GC, since finalization thread is with high priority starts cleaining and  Worker threads (with same priority) also runs at same time. with WaitForPendingFinalizers(), worker threads will wait till finalization thread completes.

     It's better practice finalizer should be used only to free up unmanaged code and shouldn't be long.

     I hope this helps you..


    If this post answers your question, please click "Mark As Answer". If this post is helpful please click "Mark as Helpful".


    Sunday, May 6, 2012 5:22 AM
  • Hi Cap'n

    Does WaitForPendingFinalizers wait for the internal queue to become empty OR wait until the last finalizable object's finalizer has completed?

    Both. WaitForPendingFinalizers suspends the thread on which it is called and waits for the thread that is processing the freachable queue to empty the queue. This is however normally done *after* each object's Finalize method has been called on the high-priority finalization thread.

    I called Collect then WaitForPendingFinalizers then Collect again and managed to trap a thread under debug a call by the GC thread to a cleanup function AFTER all of these three previous calls!

    Working under the debugger prolonges the lifetime of objects, so this is not a good indicative.

    Is there any way to ENSURE that all finalizers - that are going to be called - have in fact been called and returned from that call?

    No. Under circumstances a certain finalizer may enter an endless loop in which case the other finalizers will not execute. Finalizers are not destructors. Their code might in fact not even have been jitted when the finalization queue gets to them. Furthermore, under low memory conditions, the CLR might not be able to compile the finalizer's code. This means your application could leak unmanaged ressource.  So, no quarantees at all.

    You *could* derive your class from System.Runtime.ConstrainedExecution.CriticalFinalizerObject to guarantee finalization for a particular object under normal conditions. The CLR does the jitting upon constructing the type, so the finalizer bits are readily available. But what if the finalizer referes to a type from another assembly, that is not available at finalization time? - The only thing we know for sure is that *if* a CriticalFinalizerObject gets finalized, it does so after all other non-critical finalizers have been called. But if the process does not exit gracefully (e.g. Task-Manager shutdown) not even this quarantee holds true. Finalizers can also be aborted when internal timing tresholds are exceeded.

    Summing it all up: Don't make assumptions about the sequence or timing of finalization.

    Marcel

    Sunday, May 6, 2012 8:03 AM