When does ExecuteCodeWithGuaranteedCleanup actually guarantee cleanup?
Asked Answered
A

1

11

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?
Alcinia answered 7/4, 2010 at 9:45 Comment(1)
Run this code on a CLR host that implements ICLRPolicyManager. SQL Server.Overpower
M
5

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

Masterpiece answered 24/12, 2011 at 1:2 Comment(1)
Old answer, so documentation and behavior may have changed, I'm not sure, but MSDN currently says "If you are calling a recursive method or plan to use a lot of stack space, you must use the RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup method.". This suggests at least that a StackOverflowException can be prevented with that method.Galileo

© 2022 - 2024 — McMap. All rights reserved.