Some Creativity

The empty try block mystery

Posted in .NET, General by Sid on April 10th, 2008

Problem:

I had used .NET Mass Downloader tool to download .NET 2.0 Framework sourcecode some time ago. While reading Timer.cs (System.Windows.Forms.Timer) and a couple of other classes I noticed something interesting.

Does the following piece of code look odd to you? Notice the empty “try” block and all processing being done in the “finally” block.


        public void Foo()
        {
            try
            {
            }
            finally
            {
                DoSomething();
                DoSomethingElse();
            }
        }

It’s (most likely, you’d think - right?) not the work of a programmer misunderstanding what was asked of him :)

Solution:

This methodology guards against a Thread.Abort call interrupting the processing. The MSDN page of Thread.Abort says that “Unexecuted finally blocks are executed before the thread is aborted”. So in order to guarantee that your processing finishes even if your thread is aborted in the middle by someone calling Abort on your thread, you can place all your code in the finally block (the alternative is to write code in the “catch” block to determine where you were before “try” was interrupted by Abort and proceed from there if you want to).

But what if your thread is aborted while code in the finally block is executing?

Again, here’s what the MSDN page says:

In the .NET Framework versions 1.0 and 1.1, there is a chance the thread could abort while a finally block is running, in which case the finally block is aborted.

That’s bad because this behavior could potentially cause leakage of resources if you have your code for freeing up resources written in the “finally” block and it got interrupted in the middle by a call to Abort.

What about .NET 2.0:

I wrote a simple program to check the behavior and on my machine running .NET 2.0 on Vista Enterprise edition, finally block isn’t interrupted even if an Abort call is made on the thread running the “finally” block.

The Code:

I had a function named LaunchThread to start the thread. This function was called from the handler for the “Load” event of the form.


        private Thread mThread;

        public void LaunchThread()
        {
            this.mThread = new Thread(ThreadMain);
            this.mThread.Start();
        }

I had a button on my form. I had a handler for its Click event which basically called Abort on the thread.


        private void button1_Click(object sender, EventArgs e)
        {
            if (this.mThread != null && this.mThread.IsAlive)
            {
                this.mThread.Abort();
                this.mThread.Join();
                MessageBox.Show("Thread Aborted");
            }
            else
            {
                MessageBox.Show("Thread already died");
            }
        }

This is what ThreadMain looked like:


        public void ThreadMain()
        {
            try
            {
            }
            finally
            {
                MessageBox.Show("Going to sleep!");
                Thread.Sleep(10000);
                MessageBox.Show("Just finished sleeping!");
            }
        }

To test the application, I ran the application, waited a couple of seconds and then clicked on the button. Here is the sequence of messages that appeared:

  • As soon as the form was launched – “Going to sleep!
  • No messages appeared in response to me clicking on the button.
  • After 10 seconds – “Just finished sleeping!”
  • And immediately after that – “Thread Aborted”

Since no message appeared in response to me clicking on the button, it is clear that Thread.Sleep call in the “finally” block was not interrupted by Abort.

Changing ThreadMain like the following, leads to different results:


        public void ThreadMain()
        {
            try
            {
                MessageBox.Show("Going to sleep!");
                Thread.Sleep(10000);
                MessageBox.Show("Just finished sleeping!");
            }
            finally
            {
            }
        }

In this case, when I clicked on the button, Thread.Sleep call was interrupted by the call to Abort as I saw the following messages:

  • As soon as the form was launched – “Going to sleep!”
  • Just after clicking on the button “Thread aborted”
Tagged with: , ,

13 Responses to 'The empty try block mystery'

Subscribe to comments with RSS or TrackBack to 'The empty try block mystery'.

  1. Raj said, on April 10th, 2008 at 1:12 pm

    Great post but even greater observation :)

  2. [...] The Empty Try Block Mystery (Siddharth Uppal) [...]

  3. Justin Etheredge said, on April 11th, 2008 at 5:57 am

    Excellent, I’m going to have to write this down somewhere!

  4. [...] The empty try block mystery I had used .NET Mass Downloader tool to download .NET 2.0 Framework sourcecode some time ago. While reading Timer.cs (System.Windows.Forms.Timer) and a couple of other classes I noticed something interesting. [...]

  5. Igor said, on April 11th, 2008 at 7:16 am

    Cool!

  6. Will said, on April 11th, 2008 at 9:31 am

    The finally{} block is a critical section. There are other ways of creating critical sections, such as using lock(). I know lock won’t keep a thread from aborting, but I believe there is another way to mark a section as critical that will keep the thread abort monster away. But I don’t have my CLR Via C# handy and can’t remember it.

    This is also an example why you need to be VERY careful of what you do in a finally block. If you get into a race condition within one, good luck recovering.

  7. Sid said, on April 11th, 2008 at 10:11 am

    Thanks everyone for comments. It’s encouraging :)

    @Will,

    “finally” isn’t a critical section by itself. In general, you can have two threads executing the finally block of the same method at the same time. However, “lock” uses “try” and “finally” under the hood.

    The following piece of code:

    lock(orange)
    {
    DoSomething();
    }

    … is munged by the compiler to IL achieving the following:

    Monitor.Enter(orange);
    try
    {
    DoSomething();
    }
    finally
    {
    Monitor.Exit(orange);
    }

    So you are right in that, the “finally” generated by the compiler when it sees “lock” is a critical section because of the Monitor.Enter call that preceded it. But I’m not sure if you were thinking that deep :) “finally” isn’t a critical section on its own.

    As for other alternatives to “lock”, one could use any of Monitor, Mutex or Semaphore to implement critical sections. Not sure if you were referring to them.

  8. regev said, on April 12th, 2008 at 10:50 pm

    Thanks for this enlightening post.

  9. [...] The empty try block mystery - Siddharth Uppal highlights an interesting tip discovered by reading the .NET Framework code. [...]

  10. [...] The empty try block mystery [...]

  11. Guy said, on April 16th, 2008 at 6:03 am

    Great post

  12. [...] The empty try block mystery [...]

  13. [...] why you would have a try/finally with an empty “try” in the first place, you might find an earlier article of mine [...]

Leave a Reply