Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Aren't destructors guaranteed to finish running?

Destructors are weird. I was attempting to eliminate the need of using the disposable pattern by using 'smart' reference management, ensuring that the garbage collector could collect objects at the correct time. In one of my destructors I had to wait for an event from another object, which I noticed it didn't. The application simply shut down and the destructor was terminated in middle of execution. I'd expect a destructor is always allowed to finish running, but as the following test indicates that is not true.

using System;
using System.Diagnostics;
using System.Threading;


namespace DestructorTest
{
    class Program
    {
        static void Main( string[] args )
        {
            new DestructorTest();
            new LoopDestructorTest();
            using ( new DisposableTest() ) { }
        }
    }

    class DestructorTest
    {
        ~DestructorTest()
        {
            // This isn't allowed to finish.
            Thread.Sleep( 10000 );
        }       
    }

    class LoopDestructorTest
    {
        ~LoopDestructorTest()
        {           
            int cur = 0;
            for ( int i = 0; i < int.MaxValue; ++i )
            {
                cur = i;
            }
            // This isn't allowed to finish.
            Debug.WriteLine( cur );
        }
    }

    class DisposableTest : IDisposable
    {
        public void Dispose()
        {
            // This of course, is allowed to finish.
            Thread.Sleep( 10000 );
        }
    }
}

So, aren't destructors guaranteed to finish running?

like image 575
Steven Jeuris Avatar asked Mar 30 '12 11:03

Steven Jeuris


People also ask

Why did the destructor not execute?

The memory is allocated using the new method , so just use delete at the position where you want to free its memory. If you have allocated the memory to the variable using the first case mentioned above, then the variable gets automatically destroyed at the end of the program. Hope this helps you.

Is destructor called only once?

Destructor has the same name as their class name preceded by a tilde (~) symbol. It is not possible to define more than one destructor. The destructor is only one way to destroy the object create by constructor.

Is destructor always called in Python?

A destructor method is called when all references to an object have been destroyed. In Python, the __del__() method is referred to as a destructor method. Destructors aren't as important in Python as they are in C++, because Python contains a garbage collector that takes care of memory management automatically.

How many times will the destructor be called?

Why is the destructor being called three times?


1 Answers

So, aren't destructors guaranteed to finish running?

No. From what I remember, when the process terminates it gives finalizers a couple of seconds to execute, but then terminates the process abruptly. You wouldn't want a bad finalizer to prevent a process from ever finishing, would you?

You should regard finalization as a "best effort" clean-up - in particular, it's not going to happen in situations where the whole system is abruptly shut down, such as BSOD or power outage.

EDIT: I've found some pseudo-documentation in the form of a blog post from Joe Duffy:

If a lock was orphaned in the process of stopping all running threads, then, the shutdown code path will fail to acquire the lock. If these acquisitions are done with non-timeout (or long timeout) acquires, a hang will ensue. To cope with this (and any other sort of hang that might happen), the CLR annoints a watchdog thread to keep an eye on the finalizer thread. Although configurable, by default the CLR will let finalizers run for 2 seconds before becoming impatient; if this timeout is exceeded, the finalizer thread is stopped, and shutdown continues without draining the rest of the finalizer queue.

like image 110
Jon Skeet Avatar answered Dec 08 '22 12:12

Jon Skeet