Thread.Abort() and finally block

  • Thread starter Thread starter Bill
  • Start date Start date
B

Bill

Say I have a childThread currently is running a finally block to
cleanup external resources. At the same time the main thread calls
childThread.Abort(). The question is: when the ThreadAbortException
is thrown, does the childThread finish the remaining code in the
finally block?
 
Bill said:
Say I have a childThread currently is running a finally block to
cleanup external resources. At the same time the main thread calls
childThread.Abort(). The question is: when the ThreadAbortException
is thrown, does the childThread finish the remaining code in the
finally block?

Do the experiment.
This is the best way to find answer to such kind of questions.
Write a simple piece of code the models the situation and see what it does.
I.e. have a thread that sleeps for, say, 10 seconds in the final block and
then prints some message. Then have main thread start it, wait 2 seconds
and abort it. See if the message gets printed.

Off the top of my head, without writing and running the above example,
I believe the answer is "no". I.e., "finally" block will not be completed.

Ivan
 
The finally block is guaranteed to be called. There are very few exceptions
to this rule. Thread aborts aren't one of them.
 
From the help file:

"Unexecuted finally blocks are executed before the thread is aborted; this
includes any finally block that is executing when the exception is thrown."

-Rob Teixeira [MVP]
 
If you are referring to code in a try block that is correct. However, the OP
asked what happens if the finally block itself is interrupted. The finally
block in v1.1. will be interrupted.
 
That may be true for Longhorn but for the shipping version the finally block
will be interrupted.

Pls post the link to the help file so we can evaluate it.
 
The finally block can be interrupted.

There is one other little known way that finally blocks will not be
executed. If you have background threads (threadpool threads, manual
threads, etc.) running with finally blocks in them and you exit from the
last foreground thread in your app, the runtime will shutdown your
application (you can also force this yourself by calling Environment.Exit).
When this happens the runtime will suspend all threads except for the thread
it used to run finalizers. It never unwinds any of the threads in your app,
so no finally blocks at all will run. Object Finalizers still get called but
finally blocks never run.
 
Alvin Bruney said:
The finally block is guaranteed to be called.
There are very few exceptions
to this rule. Thread aborts aren't one of them.

Finally block *is* called.
It is just not finished, since exception is thrown in the middle of it.

Do the experiment, as I suggested. Don't blindly believe the guarantees.

This program illustrates my point:

//-------------------------------------------------------------------------
using System;
using System.Threading;

namespace AbortThreadWhileInFinallyBlock
{
class Program
{
static int Indicator = 0;

static void MyThread()
{
try
{
Console.WriteLine("In try");
}
finally
{
Console.WriteLine("Start finally");
Thread.Sleep(10000);
Indicator = 1;
Console.WriteLine("End finally");
}

}

static void Main(string[] args)
{
Thread T = new Thread(new ThreadStart(MyThread));
T.Start();
Thread.Sleep(2000);
Console.WriteLine("Aborting the thread...");
T.Abort();
Console.WriteLine("Done aborting the thread. Indicator is {0}", Indicator);
}
}
}
//-------------------------------------------------------------------------

On my machine it prints this:

In try
Start finally
Aborting the thread...
Done aborting the thread. Indicator is 0

As you can see, "end finally" was not printed, and indicator value
was not set to one. The guarantee did not work.

Ivan
 
I completely expected the finally block to terminate cleanly. I've got the
same results as you by the way, which leads me to believe that it is
possible, theoretically at least, for the finally block to not be called if
a thread abort exception occurs immediately at the point of entry into a
finally block. At least that is what the code indicates, I don't believe the
literature supports this though. ???

--
Regards,
Alvin Bruney
Got DotNet? Get it here...
http://www.networkip.net/dotnet/tidbits/default.htm
Ivan Krivyakov said:
"Alvin Bruney" <vapor at steaming post office> wrote in message news:%[email protected]...
The finally block is guaranteed to be called.
There are very few exceptions
to this rule. Thread aborts aren't one of them.

Finally block *is* called.
It is just not finished, since exception is thrown in the middle of it.

Do the experiment, as I suggested. Don't blindly believe the guarantees.

This program illustrates my point:

//-------------------------------------------------------------------------
using System;
using System.Threading;

namespace AbortThreadWhileInFinallyBlock
{
class Program
{
static int Indicator = 0;

static void MyThread()
{
try
{
Console.WriteLine("In try");
}
finally
{
Console.WriteLine("Start finally");
Thread.Sleep(10000);
Indicator = 1;
Console.WriteLine("End finally");
}

}

static void Main(string[] args)
{
Thread T = new Thread(new ThreadStart(MyThread));
T.Start();
Thread.Sleep(2000);
Console.WriteLine("Aborting the thread...");
T.Abort();
Console.WriteLine("Done aborting the thread. Indicator is {0}", Indicator);
}
}
}
//-------------------------------------------------------------------------

On my machine it prints this:

In try
Start finally
Aborting the thread...
Done aborting the thread. Indicator is 0

As you can see, "end finally" was not printed, and indicator value
was not set to one. The guarantee did not work.

Ivan
 
I completely expected the finally block to terminate cleanly. I've got the
same results as you by the way, which leads me to believe that it is
possible, theoretically at least, for the finally block to not be called if
a thread abort exception occurs immediately at the point of entry into a
finally block. At least that is what the code indicates, I don't believe the
literature supports this though. ???

No - it's not that the finally block doesn't *start* executing - it's
that the thread is aborted while the finally block is *already*
executing. It's not like it's "at the point of entry" of the finally
block - it's slap bang in the middle.

Aborting threads is basically a bad idea, IMO.
 
You misread what I said; we are in agreement.

When a ThreadAbortException is raised in a thread, then if the thread is
executing code in a try block the finally block will be executed. However,
if the code is already executing in the finally block the finally block will
be interrupted and will not complete.

Further, if you exit the process (e.g. with Environment.Exit or by allowing
the last foreground thread to exit) none of the finally blocks will execute.
All threads are suspended and are never resumed.

Ivan Krivyakov said:
"Alvin Bruney" <vapor at steaming post office> wrote in message news:%[email protected]...
The finally block is guaranteed to be called.
There are very few exceptions
to this rule. Thread aborts aren't one of them.

Finally block *is* called.
It is just not finished, since exception is thrown in the middle of it.

Do the experiment, as I suggested. Don't blindly believe the guarantees.

This program illustrates my point:

//-------------------------------------------------------------------------
using System;
using System.Threading;

namespace AbortThreadWhileInFinallyBlock
{
class Program
{
static int Indicator = 0;

static void MyThread()
{
try
{
Console.WriteLine("In try");
}
finally
{
Console.WriteLine("Start finally");
Thread.Sleep(10000);
Indicator = 1;
Console.WriteLine("End finally");
}

}

static void Main(string[] args)
{
Thread T = new Thread(new ThreadStart(MyThread));
T.Start();
Thread.Sleep(2000);
Console.WriteLine("Aborting the thread...");
T.Abort();
Console.WriteLine("Done aborting the thread. Indicator is {0}", Indicator);
}
}
}
//-------------------------------------------------------------------------

On my machine it prints this:

In try
Start finally
Aborting the thread...
Done aborting the thread. Indicator is 0

As you can see, "end finally" was not printed, and indicator value
was not set to one. The guarantee did not work.

Ivan
 
Jon Skeet said:
No - it's not that the finally block doesn't *start* executing - it's
that the thread is aborted while the finally block is *already*
executing. It's not like it's "at the point of entry" of the finally
block - it's slap bang in the middle.

Aborting threads is basically a bad idea, IMO.
It's supposed to be fixed in Longhorn, in which case finally blocks will no
longer be interrupted. It still doesn't address (so far as I know) what
happens when the application is exiting.
 
right,
but don't you see the problem though. you write a multithreaded app, where
you touch a database. In a finally construct, you free the resources. Guess
what happens before you get to the part where you free the resources. Boom,
a thread abort. Welcome to memory leak avenue, or gowd forbid you had a file
open and was hoping to close it. I can't be certain that the literature
indicates that a finally construct will execute to completion, I believe
that was probably inferred on my part based on the wording of the
literature.

Put another way, what is the point of a finally construct if it leads to
misbehavior? Should I just stay away from using abort? Not a bad price to
pay, BUT a thread can be aborted outside of your code as well. It's a
lose/lose situation.

Infact, depending on where your thread gets yanked off the stack, it could
never see the face of a finally construct. Consider:

[snip]
finally
//abort right here on entry
{
[snip]

the probability of this occuring increases as the complexity of a
multithreaded app grows.
 
You are correct in that this is a lose/lose. That's why MSFT is correcting
this. There are other problems besides this, but this is a bad one.

In the meantime, if you have mission critical cleanup code one option is to
add a try-catch handler inside the finally block, so that if it catches a
ThreadAbortException you can retry the finally logic. It's ugly but it works
(I've tested it).

The best way to prevent a problem is to avoid it....don't throw any
ThreadAbortExceptions, and if unloading an AppDomain, use signaling between
your threads to know when they are at a safe point.



Alvin Bruney said:
right,
but don't you see the problem though. you write a multithreaded app, where
you touch a database. In a finally construct, you free the resources. Guess
what happens before you get to the part where you free the resources. Boom,
a thread abort. Welcome to memory leak avenue, or gowd forbid you had a file
open and was hoping to close it. I can't be certain that the literature
indicates that a finally construct will execute to completion, I believe
that was probably inferred on my part based on the wording of the
literature.

Put another way, what is the point of a finally construct if it leads to
misbehavior? Should I just stay away from using abort? Not a bad price to
pay, BUT a thread can be aborted outside of your code as well. It's a
lose/lose situation.

Infact, depending on where your thread gets yanked off the stack, it could
never see the face of a finally construct. Consider:

[snip]
finally
//abort right here on entry
{
[snip]

the probability of this occuring increases as the complexity of a
multithreaded app grows.

--
Regards,
Alvin Bruney
Got DotNet? Get it here...
http://www.networkip.net/dotnet/tidbits/default.htm
called
believe
 
It's amazing how much new stuff I learn everyday just by hanging around this
dump :-)

i meant that in a good way - dry humor
--
Regards,
Alvin Bruney
Got DotNet? Get it here...
http://www.networkip.net/dotnet/tidbits/default.htm
Dave said:
You are correct in that this is a lose/lose. That's why MSFT is correcting
this. There are other problems besides this, but this is a bad one.

In the meantime, if you have mission critical cleanup code one option is to
add a try-catch handler inside the finally block, so that if it catches a
ThreadAbortException you can retry the finally logic. It's ugly but it works
(I've tested it).

The best way to prevent a problem is to avoid it....don't throw any
ThreadAbortExceptions, and if unloading an AppDomain, use signaling between
your threads to know when they are at a safe point.



Alvin Bruney said:
right,
but don't you see the problem though. you write a multithreaded app, where
you touch a database. In a finally construct, you free the resources. Guess
what happens before you get to the part where you free the resources. Boom,
a thread abort. Welcome to memory leak avenue, or gowd forbid you had a file
open and was hoping to close it. I can't be certain that the literature
indicates that a finally construct will execute to completion, I believe
that was probably inferred on my part based on the wording of the
literature.

Put another way, what is the point of a finally construct if it leads to
misbehavior? Should I just stay away from using abort? Not a bad price to
pay, BUT a thread can be aborted outside of your code as well. It's a
lose/lose situation.

Infact, depending on where your thread gets yanked off the stack, it could
never see the face of a finally construct. Consider:

[snip]
finally
//abort right here on entry
{
[snip]

the probability of this occuring increases as the complexity of a
multithreaded app grows.

--
Regards,
Alvin Bruney
Got DotNet? Get it here...
http://www.networkip.net/dotnet/tidbits/default.htm
Jon Skeet said:
<"Alvin Bruney" <vapor at steaming post office>> wrote:
I completely expected the finally block to terminate cleanly. I've
got
the
same results as you by the way, which leads me to believe that it is
possible, theoretically at least, for the finally block to not be
called
if
a thread abort exception occurs immediately at the point of entry
into
 
Help files and real systems can act differently. A bug in the CLR aborts the
finalizer.
This will be (actually is) solved in the widbey realease
Willy.
 
Back
Top