This is the third part of the Types and Programming Languages series. For your convenience you can find other parts in the table of contents in Part 1 — Do not return in finally
Let’s take the following code:
1 2 3 4 5 |
try{ throw new Exception("Exception 1"); }finally{ // cleanup } |
Let’s say there is no catch block anywhere on this thread. What’s going to happen?
That depends on the platform. For instance C# finally documentation says:
1 |
Within a handled exception, the associated finally block is guaranteed to be run. However, if the exception is unhandled, execution of the finally block is dependent on how the exception unwind operation is triggered. That, in turn, is dependent on how your computer is set up. |
so the finally block may not be executed. JVM guarantees finally is executed according to this.
But the things are even more interesting because they may depend on the exception type. For instance, .NET has HandleProcessCorruptedStateException attribute:
1 2 3 |
Corrupted process state exceptions are exceptions that indicate that the state of a process has been corrupted. We do not recommend executing your application in this state. By default, the common language runtime (CLR) does not deliver these exceptions to managed code, and the try/catch blocks (and other exception-handling clauses) are not invoked for them. If you are absolutely sure that you want to maintain your handling of these exceptions, you must apply the HandleProcessCorruptedStateExceptionsAttribute attribute to the method whose exception-handling clauses you want to execute. The CLR delivers the corrupted process state exception to applicable exception clauses only in methods that have both the HandleProcessCorruptedStateExceptionsAttribute and SecurityCriticalAttribute attributes. |
So your application may survive but not all finally blocks may get executed.
Now similar question arises when instead of throwing exception you exit your application by calling exit()
. Is the finally going to be run?
Why would we care? Because we typically release resources in the finally block. If these resources are local to the process then it’s not a big deal, but once you start using interprocess things (like system-wide mutexes) then it’s important to release them otherwise the other user may not know if the protected state is corrupted or not.
Not to mention that unhandled exception may (.NET) or may not (JVM) take whole application down.
Takeaway? Always put a global try-catch
handler on the thread.