Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Time of finally execution

Take this code:

using System;

namespace OddThrow
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                throw new Exception("Exception!");
            }
            finally
            {
                System.Threading.Thread.Sleep(2500);
                Console.Error.WriteLine("I'm dying!");
                System.Threading.Thread.Sleep(2500);
            }
        }
    }
}

Which gives me this output:

Unhandled Exception: System.Exception: Exception!
   at OddThrow.Program.Main(String[] args) in C:\Documents and Settings\username
\My Documents\Visual Studio 2008\Projects\OddThrow\OddThrow\Program.cs:line 14
I'm dying!

My question is: why does the unhandled exception text occur before the finally's? In my mind, the finally should be excuted as the stack unwinds, before we even know that this exception is unhandled. Note the calls to Sleep() - these occur after the unhandled exception is printed, as if it was doing this following:

  1. Unhandled exception text/message
  2. Finally blocks.
  3. Terminate application

According to the C# standard, §8.9.5, this behaviour is wrong:

  • In the current function member, each try statement that encloses the throw point is examined. For each statement S, starting with the innermost try statement and ending with the outermost try statement, the following steps are evaluated:
    • If the try block of S encloses the throw point and if S has one or more catch clauses, the catch clauses are examined in order of appearance to locate a suitable handler for the exception. The first catch clause that specifies the exception type or a base type of the exception type is considered a match. A general catch clause (§8.10) is considered a match for any exception type. If a matching catch clause is located, the exception propagation is completed by transferring control to the block of that catch clause.
    • Otherwise, if the try block or a catch block of S encloses the throw point and if S has a finally block, control is transferred to the finally block. If the finally block throws another exception, processing of the current exception is terminated. Otherwise, when control reaches the end point of the finally block, processing of the current exception is continued.
  • If an exception handler was not located in the current function member invocation, the function member invocation is terminated. The steps above are then repeated for the caller of the function member with a throw point corresponding to the statement from which the function member was invoked.
  • If the exception processing terminates all function member invocations in the current thread, indicating that the thread has no handler for the exception, then the thread is itself terminated. The impact of such termination is implementation-defined.

Where am I going wrong? (I've got some custom console error messages, and this is in-the-way. Minor, just annoying, and making me question the language...)

like image 981
Thanatos Avatar asked May 19 '09 20:05

Thanatos


3 Answers

The standard's statements about the order of execution are correct, and not inconsistent with what you are observing. The "Unhandled exception" message is allowed to appear at any point in the process, because it is just a message from the CLR, not actually an exception handler itself. The rules about order of execution only apply to code being executed inside the CLR, not to what the CLR itself does.

What you've actually done is expose an implementation detail, which is that unhandled exceptions are recognised by looking at a stack of which try{} blocks we are inside, rather than by actually exploring all the way to the root. Exceptions may or may not be handled by looking at this stack, but unhandled exceptions are recognised this way.

As you may be aware, if you put a top-level try{}catch{} in your main function, then you will see the behaviour you expect: each function's finally will be executed before checking the next frame up for a matching catch{}.

like image 131
kdt Avatar answered Oct 07 '22 22:10

kdt


I could be way off base in the way I'm reading things...but you have a try finally block without a catch.

Juding by the description you posted, since the Exception is never caught, it bubbles up to the caller, works it's way up through the stack, is eventually unhandled, the call terminates, and then the finally block is called.

like image 2
Justin Niessner Avatar answered Oct 07 '22 22:10

Justin Niessner


The output is actually from the default CLR exception handler. Exception Handlers occur before the finally block. After the finally block the CLR terminates because of the unhandled exception (it can't terminate before, as c# guarantees [1] that the finally clause is called).

So I'd say it's just standard behaviour, exception handling occurs before finally.

[1] guranteed during normal operation at least in absence of internal runtime errors or power outage

like image 2
Ben Schwehn Avatar answered Oct 07 '22 22:10

Ben Schwehn