Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to determine whether a .NET exception is being handled?

We're investigating a coding pattern in C# in which we'd like to use a "using" clause with a special class, whose Dispose() method does different things depending on whether the "using" body was exited normally or with an exception.

To the best of my understanding, the CLR keeps track of the current exception being handled until it's been consumed by a "catch" handler. However it's not entirely clear whether this information is exposed in any way for the code to access. Do you know whether it is, and if so, how to access it?

For example:

using (var x = new MyObject())
{
    x.DoSomething();
    x.DoMoreThings();
}

class MyObject : IDisposable
{
    public void Dispose()
    {
        if (ExceptionIsBeingHandled)
            Rollback();
        else
            Commit();
    }
}

This looks almost like System.Transactions.TransactionScope, except that success/failure is not determined by a call to x.Complete(), but rather based on whether the using body was exited normally.

like image 596
Roman Starkov Avatar asked Nov 29 '09 13:11

Roman Starkov


People also ask

What is exception handling in Java?

Exception handling uses the try, catch, and finally keywords to try actions that may not succeed, to handle failures when you decide that it's reasonable to do so, and to clean up resources afterward. Exceptions can be generated by the common language runtime (CLR), by .NET or third-party libraries, or by application code.

What happens if you test a method without exception handling?

In this example, a method tests for division by zero and catches the error. Without the exception handling, this program would terminate with a DivideByZeroException was unhandled error.

Is it possible to handle every exception?

At the same time, you don't want to try to handle every single exception on the face of the earth, because 'handling' in this sense typically transforms into 'suppression', which is way worse than just letting the application fail (gracefully). Show activity on this post.

Is it recommended to throw system exceptions in an application?

It's not recommended that one throws or catches a System Exception as that is thrown by CLR automatically. When an error occurs, the system or the currently executing application reports it by throwing an exception containing information about the error.


2 Answers

https://www.codewrecks.com/post/old/2008/07/detecting-if-finally-block-is-executing-for-an-manhandled-exception/ describes a "hack" to detect if your code is executed in exception handling mode or not. It uses Marshal.GetExceptionPointers to see if an exception is "active".

But keep in mind:

Remarks

GetExceptionPointers is exposed for compiler support of structured exception handling (SEH) only. NoteNote:

This method uses SecurityAction.LinkDemand to prevent it from being called from untrusted code; only the immediate caller is required to have SecurityPermissionAttribute.UnmanagedCode permission. If your code can be called from partially trusted code, do not pass user input to Marshal class methods without validation. For important limitations on using the LinkDemand member, see Demand vs. LinkDemand.

like image 166
VolkerK Avatar answered Sep 18 '22 15:09

VolkerK


Not an answer to the question, but just a note that I never ended up using the "accepted" hack in real code, so it's still largely untested "in the wild". Instead we went for something like this:

DoThings(x =>
{
    x.DoSomething();
    x.DoMoreThings();
});

where

public void DoThings(Action<MyObject> action)
{
    bool success = false;
    try
    {
        action(new MyObject());
        Commit();
        success = true;
    }
    finally
    {
        if (!success)
            Rollback();
    }
}

The key point is that it's as compact as the "using" example in the question, and doesn't use any hacks.

Among the drawbacks is a performance penalty (completely negligible in our case), and F10 stepping into DoThings when I actually want it to just step straight to x.DoSomething(). Both very minor.

like image 38
Roman Starkov Avatar answered Sep 19 '22 15:09

Roman Starkov