2005 2006 2007 2008 2009 2010 2011 2015 2016 2017 aspnet azure csharp debugging elasticsearch exceptions firefox javascriptajax linux llblgen mongodb powershell projects python security services silverlight training videos wcf wpf xag xhtmlcss

The Uncatchable Exception

There's once aspect of exception handling that I've found that many seasoned .NET veterans know about. Take a look at the following code...

class Node {
    private Node node;

    public Node ChildNode {
        get {
            if (node == null) {
                node = new Node( );
            }
            return node;
        }
        set { node = value; }
    }
}

class Program
{
    static void ProcessNode(Node node) {
        ProcessNode(node.ChildNode);
    }

    static void Main(string[] args) {
        try {
            ProcessNode(new Node( ));
        }
        catch (StackOverflowException ex) {
            Console.WriteLine(ex.Message);
        }
        catch (Exception ex) {
            Console.WriteLine(ex.Message);
        }
    }
}

Code Segment 1

What do you figure the output will be? Well, most people say the output is something like "Operation caused a stack overflow." That's a nice guess, but this exception thrown from the CLR is actually not catchable. This is the uncatchable exception. It actually jumps directly outside of your try block and shuts your application down. What you actually see is what's in the below figure.

StackOverFlowException

Figure 1

The CLR does not allow you to have infinite loops in your applications at all. So much so in fact that it will literally kill your entire application to make sure you follow the rules.

Now, if you're thinking about it... you may be think "CLR threw it? Hmm... I wonder... I read something about the ability to throw things that aren't exceptions". So, you may be tempted to try this...

try {
    ProcessNode(new Node( ));
}
catch {
    Console.WriteLine("Unknown exception");
}

Code Segment 2

This actually doesn't help the situation at all. Actually, if you've read my previous blog entry on the RuntimeWrappedException, then you would know about the .NET wrapping plan. Under .NET's default rules, thrown objects which do not inherit from System.Exception are wrapped in an instance of RuntimeWrappedException. So, even if the exception thrown was one of those, it would have been caught by the original code anyhow.

This StackOverFlowException application failure is actually a very helpful rule the CLR enforces. It forces you to go back and make sure you don't have a recursion bug in your code, because this is not really a user-specific exception it's literally a bug in your application. So, before you throw a fit when you see this, just go back and find the bug in your recursion code.

It's important to note however, that there's nothing inherently special about the StackOverFlowException itself. Take a look at this code...

static void ThrowStackOverFlowException( ) {
    throw new StackOverflowException( );
}

static void Main(string[] args) {
    try {
        ThrowStackOverFlowException( );
    }
    catch (StackOverflowException ex) {
        Console.WriteLine(ex.Message);
    }
}

Code Segment 3

This time your output really is "Operation caused a stack overflow.". So, if you throw it yourself you can catch it. The uncatchable exception isn't really StackOverflowException, but rather the CLR's throwing of the StackOverflowException.

There are other ways to completely kill an application. One of the more subtle of ways is via use of System.Environment.FastFail(String message). This static method will immediately kill and application and will not be caught by any catch blocks anywhere. So, if you really want to screw up an application simply do the following...

[Serializable]
public class SalesOrderException : Exception
{
    public SalesOrderException( ) {
        Environment.FailFast(String.Empty);
    }

    // More constructors go here...
}

Code Segment 4

Now every time your application has a SalesOrderException, it will explode into pieces. There's absolutely no way to recover from this. The above code is something that a disguntled employee would love to check in.

That said, looking at it in another light, Environment.FastFail(String) can actually be a great debugging tool. For example, say you have an application that is just downright giving you some weird output. You have no idea why. You know it's wrong, but there are just no exceptions bubbling to the surface to help you out. Well, if you have access to Visual Studio 2005's Debug->Exceptions... menu item, you can actually tell Visual Studio to allow you to see those first chance exceptions. If you don't have that, however you can put Environment.FastFail(String) in an exception, and use deductive reasoning and process of elimination to find out where your problem in.

You may actually be wondering "What is the point of Environment.FastFail(String)?" It's actually quite useful for anyone severely uptight about security or someone withing really low level in a system. If you're absolutely sure there's an unrecoverable corruption in your system, then you can call this method to kill this application. Basically what you're doing is "blue screening your application". The operating system is untouched, but you application is gone. Another situation someone can use Environment.FastFail in in security situations. If you absolutely need to verify some piece of security for the application to continue at all (i.e. you don't want anyone to catch an exception you throw and continue insecure), then you can use this method to "bluescreen" the app.

Constrainted try with retry mechanism for .NET 2.0

Lately I've been working on building a framework of abstractions and features that I feel are rather missing from my daily life. One of these features is a try/retry. In the past I used gotos and a ton of code to do this...but such extra coding was the nature of .NET 1.x. This is the world of .NET 2.0 and therefore I can take it to the next level! My new ExceptionFramework includes a few items to help me with exceptions and I figured I would share the following bit with the world.

using System;

public static class ExceptionManager
{
    public static void TryWithRetryConstraints(
        Int32 retryCount,
        Int32 sleepTime,
        ExceptionConstraintCollection constraints,
        ExceptionTryBlock tryBlock,
        ExceptionCatchBlock catchBlock) {
        Int32 n = 0;
    retry:
        try {
            tryBlock.DynamicInvoke( );
        }
        catch (Exception ex) {
            if (++n < retryCount) {
                foreach (Object constraint in constraints) {
                    if (constraint is Type) {
                        Boolean isException = false;
                        if (((Type)constraint).Name == "Exception") {
                            isException = true;
                        }

                        Type parent = ((Type)constraint).BaseType;
                        while (!isException && parent.Name != "Object") {
                            if (parent.Name == "Exception") {
                                isException = true;
                            }
                            parent = parent.BaseType;
                        }
                        if (isException) {
                            Exception thrownException = ex;
                            while (thrownException != null) {
                                if (thrownException.GetType( ).ToString( ) == constraint.ToString( )) {
                                    Thread.Sleep(sleepTime);
                                    goto retry;
                                }

                                thrownException = thrownException.InnerException;
                            }
                        }
                    }
                    else if (constraint is String) {
                        if (ex.Message.Contains((String)constraint)) {
                            Thread.Sleep(sleepTime);
                            goto retry;
                        }
                    }
                    catchBlock.DynamicInvoke(ex);
                    return;
                }
            }
            else {
                catchBlock.DynamicInvoke(ex);
            }
        }
    }
}

Here are some of the support items...

public delegate void ExceptionTryBlock( );
public delegate void ExceptionCatchBlock(Exception ex);

public class ExceptionConstraintCollection : Collection<object>
{
    public ExceptionConstraintCollection( ) {
        // Always declare default constructors!
    }

    public ExceptionConstraintCollection(params object[] constraintSet) {
        for (int n = 0; n < constraintSet.Length; n++) {
            this.Add(constraintSet[n]);
        }
    }
}

This version allows me to retry only for certain types of failures. There is a simplified version which doesn't take the constraints, but this is one is a bit more useful for my scenarios (I actually think it's a good idea to always constrain it!) I found that the times I wanted to retry involved cases where I either wanted to retry based on a certain type of exception type or based on some text in the string.

Here's is how I use this version of the try/retry in one of my WPF applications. This is my little way of testing my laptop's RAM speed (as well as the CLR speed). I would grab 1GB of ram, free it, and quickly try to get it again (won't work). The below try/retry helps me get a feel or how fast .NET 2.0 can free up the memory and get it again (sometimes it CAN get the 1GB back).

First, I set up the constraints collection which holds the types and strings to which retries will be constrained to. This could of course be inline with the primary call.

ExceptionConstraintCollection constraints = new ExceptionConstraintCollection(
        typeof(OutOfMemoryException),
        "invocation");

Here is the actual call to the try/retry. I tell the try/retry manager how many times to retry (6), how many milliseconds to wait between each try (1000), what constraints to put on the try/retry (the above constraints collection), the logic to run as the try block (a delegate; anonymous in this case), and the code to run as the catch block (also a delegate; also anonymous in this case) and then let it do all the work for me.

ExceptionManager.TryWithRetryConstraints(6, 1000, constraints,
    delegate {
        group = new MemoryGroup();
        MessageBox.Show("Success");
    },
    delegate(Exception ex) {
        ExceptionManager.Report("Unable to allocate memory group.", ex);
    });

Now there are some obvious issues with this. The first: speed. Well, that's the nature of abstraction. You get ease of use and simplicity to life, but it costs a bit. The second is...this just seem weird, doesn't it? It just seems like there's a whole new bag of issues associated with this. Actually, this doesn't really bother me either. I'm keeping my code small enough so that I don't break the Ritcher anonymous delegate rule (never more than 3 lines of code in an anonymous block including comments) and I'm keeping in my mind that top level exceptions will really have the text of "Exception has been thrown by the target of an invocation." (which is, of course, true, but this means I better not be doing this stuff straight with COM interop!) As long as I keep that last one in mind I should be fine.

In any case, this has really been helping me out and have been proving to be a very powerful solution to the lack of a try/retry in the CLR.

.NET 2.0 trycatch and trycatch(Exception ex)

One thing that I found rather interesting about .NET 2 that's different from .NET v1 is how v2 handles non-exception throwables differently.

First, a little background...

In case you don't know, the following two pieces of code are completely different.

try {
    Thrower.Start( );
}
catch (System.Exception ex) {
    System.Console.Write("Error!");
}
try {
    Thrower.Start( );
}
catch {
    System.Console.Write("Error!");
}

The difference is not that the first catches exceptions from unmanaged code and the second second doesn't, the first actually does catch those exceptions. The difference is also a bit more important than the mere fact that in the first one case we capturing the exception data in an exception type and in the other we aren't. The real difference stems from the fact that that in .NET you can throw things other than exceptions and in v1 you used the latter code to catch those non-exception throwables.

Here's an example of how to throw a non-exception. Yeah, you basically have to use the IL, or a compiler that doesn't check for this stuff.

// ThrowerLib.il
.assembly ThrowerLib { }

.class public Thrower {
    .method static public void Start( ) {
        ldstr "Oops"
        throw
        ret
    }
}

Here we are throwing "Oops". That's obviously a string, not something derived from System.Exception. In v1 you could use try{}catch(Exception ex) {} as a catch all for all exceptions, but that would not catch this error as it's not an exception. To catch this, you would also have a catch{} at the end.

OK, so how's v2 different? In this world, the non-exception item thrown is wrapped up in a real exception. So, in .NET v2 you can actually use your normal try {} catch(Exception ex){ } to also catch these non-exception throwables as well.

They are actually thrown as a RuntimeWrappedException. So the following app compiled an run in .NET v1 would explode into pieces, but would would gracefully end in .NET v2.

// ThrowerLib.il
.assembly ThrowerLib { }

.class public Thrower {
     .method static public void ThrowException( ) {
         ldstr "ThrowException exception from the IL world!"
         newobj instance void [mscorlib]System.Exception::.ctor(string)
         throw
         ret
     }

     .method static public void ThrowString( ) {
         ldstr "Weird exception!"
         throw
         ret
     }
}
// ThrowerHarness.cs
namespace ThrowerExample
{
    class ThrowerHarness
    {
        static void Main(string[] args) {
            try {
                Thrower.ThrowException( );
            }
            catch (System.Exception ex) {
                System.Console.WriteLine("System.Exception error: " + ex.Message);
            }
            catch {
                System.Console.WriteLine("Non System.Exception based error.");
            }

            try {
                Thrower.ThrowString( );
            }
            catch (System.Exception ex) {
                System.Console.WriteLine("System.Exception error: " + ex.Message);
            }
            catch {
                System.Console.WriteLine("Non System.Exception based error.");
            }
        }
    }
}

trycatch in .NET 2.0 - Note

Here is a comment Joe made about my previous post.

... One additional facet that will probably go (mostly) unnoticed is that you can throw exceptions across assembly boundaries, and the wrapping will occur based on the assembly-level attribute on the assembly whose catch block is being evaluated. This makes interoperability with code that isn't on the wrapping plan, e.g. COBOL or Eiffel, work seamlessly as you would expect.

...

This comment is rather hidden in how I have my page designed, but I thought it worthy of it's own posting anyhow.

trycatch in .NET 2.0 - Part 2

As I pointed out in a previous entry, try{}catch{} works differently in .NET 2.0 as it does in .NET 1.x. In 2.0, non-exception "throwables" are wrapped in a RuntimeWrappedException which can be caught by try{}catch(Exception ex){}, while, to catch then in .NET 1.x, you were required to use try{}catch{}. This led me to wonder 1) how does this work? and 2) is there even a purpose for try{}catch{} anymore?

So I started my research by... well, passing the buck, or going to the source, depending on your view on things. The first thing I did was ask Brad Abrams if he had some insights about this. He then forwarded me to Jonathan Keljo who I guess then forwarded me to Joe Duffy...sheesh what a line up! The best of the best of the best right there! Goodness, I feel like an ant...

Anyhow... here's the thing. Joe affirmed that there are at least two purposes for try{}catch{} in .NET 2.0

Here are his exact words...

(1) If your assembly doesn't have "wrapping" turned on;

(2) If you don't care to access the exception information via a variable. This can help to reduce the temptation to accidentally do a catch(Exception e){ /*...*/; throw e; } when you meant to do catch { /*...*/ throw; }.

OK cool, now what about the mechanics? Joe explains that the wrapping of RuntimeWrapperException around non-exception throwables is due to the fact that C# and VB auto opt-in all assemblies to what they call "the wrapping plan". This means there is a RuntimeCompatibilityAttribute(...) on the assembly where, in this case, WrapNonExceptionThrows=true is set. When this is the case all non-System.Exception "exceptions" get wrapped into a RuntimeWrappedException, which, as Joe points out of course does inherit from System.Exception. Conversely, if WrapNonExceptionThrows=false is set, then there is no magical wrapping.

Let's see this all in action. But before we do, last time I wrote about this I forgot to what mention happens when you compile the below code (this is the same code from the previous blog entry about this topic)

// ThrowerHarness.cs
namespace ThrowerExample
{
    class ThrowerHarness
    {
        static void Main(string[] args) {
            try {
                Thrower.ThrowException( );
            }
            catch (System.Exception ex) {
                System.Console.WriteLine("System.Exception error: " + ex.Message);
            }
            catch {
                System.Console.WriteLine("Non System.Exception based error.");
            }

            try {
                Thrower.ThrowString( );
            }
            catch (System.Exception ex) {
                System.Console.WriteLine("System.Exception error: " + ex.Message);
            }
            catch {
                System.Console.WriteLine("Non System.Exception based error.");
            }
        }
    }
}

Compiling this code actually gives the following warnings...

throwerlib.cs(16,7): warning CS1058: A previous catch clause already catches all
        exceptions. All non-exceptions thrown will be wrapped in a
        System.Runtime.CompilerServices.RuntimeWrappedException
throwerlib.cs(29,7): warning CS1058: A previous catch clause already catches all
        exceptions. All non-exceptions thrown will be wrapped in a
        System.Runtime.CompilerServices.RuntimeWrappedException

As you can see, we know at compile that try{}catch(Exception ex){} will grab the exceptions.

Here's the IL we are using, which contains the Thrower class and is referenced by the C# application.

// ThrowerLib.il
.assembly ThrowerLib { }

.class public Thrower {
    .method static public void ThrowException( ) {
        ldstr "ThrowException exception from the IL world!"
        newobj instance void [mscorlib]System.Exception::.ctor(string)
        throw
        ret
    }

    .method static public void ThrowString( ) {
        ldstr "Weird exception!"
        throw
        ret
    }
}

Of course, there's our command syntax...

ilasm /t:dll ThrowerLib.il
csc Thrower.cs /r:ThrowerLib.dll

After a successful assembly and compilation, running this application gives the following output...

System.Exception error: ThrowException exception from the IL world!
System.Exception error: An object that does not derive from System.Exception has been wrapped in a RuntimeWrappedException.

Now, what about what Joe was saying about the RuntimeCompatibilityAttribute? Well, if we were to tack the following onto our existing class, we would get absolutely no warnings. Pretty cool...

using System.Runtime.CompilerServices;
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = false)]

Not only that, but here's the output as we would expect.

System.Exception error: ThrowException exception from the IL world!
Non System.Exception based error.

As you can see it did not wrap the exception. So, now, the picture of how things work and how to modify them is a bit more complete.

You can download the code for this entry by the link below.

Joe Duffy also has an explanation of this, although his is from the Beta 2 era (I only see one change -- WrapNonClsExceptions -> WrapNonExceptionThrows; but there may be more). Here is his article.

Powered by
Python / Django / Elasticsearch / Azure / Nginx / CentOS 7

Mini-icons are part of the Silk Icons set of icons at famfamfam.com