Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When does ExecuteCodeWithGuaranteedCleanup actually guarantee cleanup?

I have been reading about Reliability Features in .NET and have written the following class to explore ExecuteCodeWithGuaranteedCleanup

class Failing
{
    public void Fail()
    {
        RuntimeHelpers.PrepareConstrainedRegions();
        try
        {
        }
        finally
        {
            RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(Code, Cleanup, "fail");
        }
    }

    private void Code(object message)
    {
        // Some code in here that will cause an exception...
    }

    private void Cleanup(object message, bool something)
    {
        Console.WriteLine(message);
        Console.ReadLine();
    }
}

I have experimented with a variety of code bodies for the Code method. These, and their runtime results are listed below

Causing an OutOfMemoryException - Cleanup does not get called

List<string> ss = new List<string>();

while (true)
{
    string s = new string('x', 1000000);

    ss.Add(s);
}

Causing a StackOverflowException - Cleanup does not get called

Code(message); // recursive call

Causing a ExecutionEngineException - Cleanup does not get called

Environment.FailFast(message.ToString());

Causing a ThreadAbortException - Cleanup does get called (however a regular try...finally can also catch this exception)

Thread.CurrentThread.Abort();

So the questions are

  • Am I using ExecuteCodeWithGuaranteedCleanup correctly?
  • When is ExecuteCodeWithGuaranteedCleanup actually useful?
like image 286
Richard Ev Avatar asked Apr 07 '10 09:04

Richard Ev


1 Answers

Some exceptions are fatal to the process and execution of user-supplied code just does not continue. The purpose of ExecuteCodeWithGuaranteedCleanup method is to so you can put your data structures back in a consistent state. If the process is going to die anyways with no way to stop it, this has no purpose. The OS (assuming it is working properly) will clean up any kernel objects automatically for you when a process ends, regardless of the reason the process ends.

As Hans hints, the ICLRPolicyManager of the host comes into play to determine which exceptions are fatal in this way when code is run in a particular host (especially SQL Server). See the nice grid at the bottom of this documentation page: ICLRPolicyManager::SetActionOnFailure Method

like image 58
Jason Kresowaty Avatar answered Nov 07 '22 11:11

Jason Kresowaty