Home > Uncategorized > Exceptions Part 4: What happens if ‘finally’ blocks always execute?

Exceptions Part 4: What happens if ‘finally’ blocks always execute?

See the Contents Page for this series of articles

It’s a widespread belief that finally blocks “always” execute, sometimes with hilarious implications.

Last time I reasoned logically that in order for our code to have predictable behaviour, we should stop it running when it becomes clear we don’t understand the state the program is in. As finally blocks are filled with little chunks of our code, it stands to reason that they shouldn’t execute when things get Ugly.

Now I’m going to discuss the specifics of what can go wrong if they are always forced to execute, as they are in a couple of popular languages, C++ and Java (and also by default in CLR-based languages).

Yes, this is a long one, but I’m going to try to start a few language wars, so it should be fun!

The first thing I should clear up is that when I say finally in the context of C++, I’m talking about destructors on objects allocated with automatic storage (local variables, parameters and temporaries). Although they don’t look alike, they are essentially blocks of code that get executed in response to leaving some scope, whether due to an exception or just ordinary flow of control.

The number one pain in the a… neck with finally blocks is when they throw exceptions. As usual, the obvious example is that a bug causes an exception to be thrown, and now something in the file system needs to be cleaned up, but then there is a problem with the clean-up code and it too throws an exception.

Remember, the finally block has not caught the first exception. But it has thrown another one. So now we have two exceptions looking for a catch block to call home. This utterly wrecks the simple model of exception handling. As a language/runtime designer, we would appear to have the following options.

  1. Discard the original exception, start propagating the new one.
  2. Discard the new exception, presumably by the equivalent of inserting a try/catch immediately inside the finally block with the catch block left empty.
  3. Form the exceptions into a list (this could use the InnerException property to form a linked list, or a class like AggregateException)
  4. Terminate the process as soon as possible – after all, things have become silly.

All of these have their problems. Discarding an exception (either way) seems fundamentally non-rigorous, and in a moment we will look closely at one of the worst things that can happen as a result. Option 3 sounds “cool” until you realise that this conflicts with the way that exceptions are caught. We specify a certain type in a catch statement; but wrapping exceptions will mean that if we get two or more simultaneous exceptions, the type of the exception object will be different, thus changing what we need to catch.

Option 4 sounds quite harsh, doesn’t it? That’s what happens in C++. Consequently most C++ programmers know the mantra: never throw from destructors, which is often effectively the same as option 2 (put a general try/catch around all the code in your destructor.)

Java and (by default) the CLR go for option 1. However (for reasons that will become clear), the regularly given advice in those environments is to simulate option 2: try to ensure exceptions never escape from finally blocks.

Given this unanimous conclusion, it seems mighty strange that finally blocks don’t have built-in “exception swallowing” behaviour. The reason they don’t is that in fact it is perfectly okay for a finally block to throw, just so long as there isn’t already an uncaught exception on the loose; recall that finally blocks run however the scope is exited, not just in response to exceptions. So sometimes it’s okay, sometimes it’s not. Tricksy finallieses!

Given this, it seems natural to demand some way to ask the environment, “Is there an uncaught exception on the loose?” Then you could check before allowing another exception to escape.

And in C++, a standard library function was added in order to answer that exact question. But it turns out to not actually solve the problem. The advice of renowned C++ expert Herb Sutter is to never use it, and to simulate option 2: never let destructors throw. Instead of a function telling you that there is an exception that has not been caught yet, you need a function that tells you if there is an exception that isn’t going to be caught at all – an is_exception_ugly() function. But that sounds almost spooky, like it can predict the future… Or does it?

In defence of C++, one advantage of option 4 is that at least you’ll find out unambiguously when you mess up. On the downside, maybe your customers will find out first, but at least it won’t go amiss. Whereas with the other popular default, option 1, information is discarded.

But maybe that’s not so bad, you wonder. After all, you had an exception, now you have another exception. It’s a fair exchange…

NO! You haven’t been paying attention! I’m extremely disappointed with you.

Some exceptions are merely Bad, but some are Ugly, and the difference is vitally important. What if one type gets turned into another? Actually, to be honest this isn’t always worth worrying about. If the second exception is Ugly, while it’s nothing to celebrate, it’s robust behaviour, in the sense that your program will soon terminate and that’s the right thing to do when there’s an Ugly exception, no matter how it is arrived at.

And Bad to Bad is okay too, because – by definition – the exception is still going to get caught (it helps if you treat all Bad exceptions in the same way, of course).

However, this leaves one miserable transformation: Ugly to Bad. This is the real killer. Or rather, the unfortunately immortal! Here’s a simulation of it in Java:

try
{
    try
    {
        throw new NullPointerException();
    }
    finally
    {
        System.out.println("finally is executing");
        throw new java.io.IOException();
    }
}
catch (java.io.IOException x)
{
    System.out.println("caught IOException");
}

System.out.println("program keeps running as if nothing had happened...");

The innermost block has a heinous bug in it, and there is no catch block for the resulting exception, so the program should be shutting down. But (altogether now…) “finally blocks always execute”, and so first we pointlessly try to delete a temporary file or something like that. But, due to some untested scenario, the file doesn’t exist yet. Of course we don’t regard that as a fatal situation, so we catch and practically ignore the resulting IOException. This means that our exception is upgraded from Ugly to Bad. And so our rotten stinking bug is entirely hidden from us.

But where it gets really amusing (I think) is in the CLR. Try running this, if you want a laugh:

try
{
    try
    {
        throw new NullReferenceException();
    }
    finally
    {
        MessageBox.Show("finally is executing");
        throw new IOException();
    }
}
catch (IOException x)
{
    MessageBox.Show("caught IOException");
}

MessageBox.Show("program keeps running as if nothing had happened...");

It’s practically identical to the Java version, except that I’m using message boxes instead of the console for a bit of variety. This is what I see on Windows 7, with either .NET Framework 3.5 or 4.0:

  • Windows Error Reporting dialog appears. I click Close the program.
  • “finally is executing”. I click OK.
  • “caught IOException”. I click OK.
  • “program keeps running as if nothing had happened…”. And it does, for as long as I want!

It really, really looked like it was going to crash, but then it didn’t. And this is not just a parlour trick. This is something that could happen in any reasonably large complex product. We never catch the NullReferenceException, we have a severe bug and the state of our program is out of control, even WER has kicked in… and yet it keeps running for as long as the user lets it. And all due to our attempt to clean up some temporary file.

It’s this kind of absurdity that terrifies people into accepting that they should never allow their finally blocks to throw. I imagine some teams might even adopt a coding standard which states that finally blocks must look like this:

finally { try
{
        
} catch {} }

I suppose you could have a template in your IDE to automatically insert that chunk of rubbish into your code with a few keystrokes. And as I’ve already noted, sometimes it is okay to throw from a finally, as long as there isn’t already an exception currently in transit.

But there is a better way! At least, in the CLR there is (sorry, Java and Standard C++ programmers):

// register custom handler for unhandled exceptions
AppDomain.CurrentDomain.UnhandledException += (sender, evt) =>
{
    Console.WriteLine("unhandled exception");
    Environment.FailFast(null);
};

Environment.FailFast(null) just kills your process stone dead, pretty much.

Actually that’s quite an extreme option – you probably want to capture plenty of information about the process before you tear it down. Or you may want to have a registry setting or similar to control what happens, to aid in tricky support scenarios. I’ve found that producing a complete stack trace (by following the InnerException chain) and writing it out to a file is very nearly always enough to pinpoint a bug, so I do that and then call Environment.FailFast(null), but it’s possible to do more sophisticated forms of information gathering. I haven’t found that to be necessary so far, but I’m planning on investigating it further when I have time.

The key point is that the UnhandledException event fires only if the exception is not going to be caught, and it does this before the stack starts unwinding. This is not as spooky as it sounds. As I mentioned last time, the way it works in the CLR is that the stack is firstly searched (in a passive, “readonly” way) to find an enclosing catch that is compatible with the exception. If the search makes it all the way past Main without finding a handler, then the exception is not going to get caught. The future of the exception is trivially predictable from a search of the stack. So in the event of an exception that is not going to be caught, before any further steps are taken by the CLR, it fires the UnhandledException. This allows you to step in and stop the finally blocks from executing in response to what you now know is an Ugly exception.

Of course, it is not necessary to examine the exception in UnhandledException to decide if its Ugly. By that point, the exception must by definition be Ugly, because you didn’t catch it. It’s too late to do anything about that now.

Interestingly, Java has a very similar looking event. The code for handling it and quitting, using an anonymous class, might look like this:

// register custom handler for unhandled exceptions
Thread.currentThread().setUncaughtExceptionHandler(

    new Thread.UncaughtExceptionHandler() {

        public void uncaughtException(
                final Thread t, final Throwable e) {

            System.out.println("Uncaught exception");
            System.exit(0);
        }
    }
);

However, a very simple test will demonstrate that on a standard JVM, all the finally blocks on the stack are executed before this callback is executed. So it runs far too late, when the damage has already been done. The “self-resurrecting” example I showed above can only be reliably avoided in Java by the discipline of always embedding a catch-all inside every finally block.

Recall that we are mostly concerned about the “upgrading” of an exception from Ugly to merely Bad. So the CLR’s UnhandledException event really does solve the most important problem for us. But it can only do so if we use catch properly, to catch specific exception types that we know we can recover safely from. We have to document to the CLR, through our use of catch, exactly which exception types are Bad, leaving the remainder Ugly.

This is the real reason why catch (Exception x) {...} or catch { } has no place in any well-formed C# program.

By the way, things are a little different in VB.NET. I claimed that a “trivial” search of the stack is all that needs to happen to detect an Ugly exception, but actually its only trivial if the language is restricted in a particular way. C# is appropriately restricted, but VB.NET is not, and I will likely get into that next time, when I get onto the subject of how exceptions are caught.

Next time: Why the whole idea of an exception class hierarchy is a hopeless myth.

Advertisements
Categories: Uncategorized Tags: , , , ,
  1. Trillian
    July 3, 2010 at 11:26 pm

    Great series of articles. I had never given much thought to unhandled exceptions and unknown program state before. You have a very solid point on the matter and provide concise information on the topic. In a word, you got me hooked, keep it up!

    • earwicker
      July 5, 2010 at 10:14 am

      Thanks, probably a couple more articles to go in this series, depends how much I can cram into one article.

  2. Trillian
    July 27, 2010 at 2:33 am

    Yay part 5, interesting insight once again. Looking forward to see what comes next!

    I’m not sure if you were planning to talk about this, but earlier this day a friend of mine told be about a peculiar situation with checked exceptions in Java. The (now deprecated) Class.newInstance method throws any exception thrown by the invoked constructor, and doesn’t declare that it can throw anything. Because of this, you can’t even write a catch clause because the compiler thinks the exception cannot happen. And let’s not talk about Unsafe.getUnsafe().throwException() (gory details here: http://www.oreillynet.com/onjava/blog/2004/09/avoiding_checked_exceptions.html). The superseding Constructor.newInstance method throws a wrapping exception when the constructor throws. But that’s still uncool as it forces the code to do an explicit type-switch on the wrapped exception (as it cannot even be re-thrown). Generally, reflection just adds to the exception type hierarchy mess, although I can’t think of a system that would be any better.

    • Trillian
      July 27, 2010 at 2:39 am

      Oops sorry, I meant to post this on the part 5 article.

  1. July 2, 2010 at 11:45 pm
  2. July 24, 2010 at 6:26 pm
  3. December 14, 2010 at 1:48 am

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: