Thread Abort and Unhandled Exception Event

  • Thread starter Thread starter pawel.kedzior
  • Start date Start date
P

pawel.kedzior

Hi

In .NET 2.0 unhandled exceptions in separate threads cause raising
unhandled exception event and terminating the process. This is true
for most exceptions, but not for ThreadAbortException, what is
reasonable.

I have verified this with following example:
class Program {
private static void thread() {
while (true){}
}
static void Main(string[] args) {
AppDomain.CurrentDomain.UnhandledException
+= new UnhandledExceptionEventHandler(handler);
Thread th = new Thread(new ThreadStart(thread))
th.Start();
Thread.Sleep(5000);
th.Abort();
Thread.Sleep(50000);
}

static void handler(object sender, UnhandledExceptionEventArgs
e) {
System.Console.WriteLine("Unhandled exception.");
}
}

While working with my, quite complex, application, where I must use
Thread.Abort() on one of my threads, I managed to get in the handler
following exception:

Exception: System.Threading.ThreadAbortException
Message: Thread was being aborted.
Source: mscorlib
at System.Reflection.Assembly.GetType(String name, Boolean
throwOnError, Boolean ignoreCase)
at System.Activator.CreateInstanceFrom(String assemblyFile, String
typeName, Boolean ignoreCase,
BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo
culture, Object[]
activationAttributes, Evidence securityInfo)
at System.AppDomain.CreateInstanceFrom(String assemblyFile, String
typeName)

The application terminated immediately because of that.

This convinced me that in some circumstances ThreadAbortException is
treated just as any other exception and can cause process crash
in .NET 2.0.
The above stack trace is a full stack trace which the exception
conveyed, and looks bit strange for me. My code never use
System.AppDomain.CreateInstanceFrom(..) directly, so I guess this is
some internal mechanism of the framwork/CLR.

Can you think what kind of my code can trigger above one ? It looks
like something related to reflection. What is exact reason that the
ThreadAbortException is not treated just as ThreadAbortException in my
example.

Generally this is very bad news for everyone who use Thread.Abort(),
because there are poor guarantees that the operation does not crash
their application.

PS. Do not suggest me using a flag to stop a thread.
 
Hello (e-mail address removed),

In .NET 2.0 unhandled exceptions in separate threads cause raising
unhandled exception event and terminating the process. This is true
for most exceptions, but not for ThreadAbortException, what is
reasonable.

The ThreadAbortException is asyn exception and can interrupt the target thread
at any point
While working with my, quite complex, application, where I must use
Thread.Abort() on one of my threads, I managed to get in the handler
following exception:

It's the well known that Thread.Abort is evil and your need to use other
ways to interrupt your thread gracefully
This convinced me that in some circumstances ThreadAbortException is
treated just as any other exception and can cause process crash
in .NET 2.0.

Yep, as async exceptions
Can you think what kind of my code can trigger above one ? It looks
like something related to reflection. What is exact reason that the
ThreadAbortException is not treated just as ThreadAbortException in my
example.

Because it can be arrised at any point, and not where you expect it
Generally this is very bad news for everyone who use Thread.Abort(),
because there are poor guarantees that the operation does not crash
their application.

Yep, it is.
PS. Do not suggest me using a flag to stop a thread.

I recommend you to read this http://www.interact-sw.co.uk/iangblog/2004/11/12/cancellation
and this http://www.dotnetconsult.co.uk/weblog/PermaLink.aspx/4f52c396-1b0d-4419-8871-6ca6992460ca






---
WBR, Michael Nemtsev [.NET/C# MVP].
My blog: http://spaces.live.com/laflour
Team blog: http://devkids.blogspot.com/

"The greatest danger for most of us is not that our aim is too high and we
miss it, but that it is too low and we reach it" (c) Michelangelo
 
Hi Michael

Thank you for your response, but this still does not explain a few
things.

I agree that async exception can emerge in any location, I can not
predict location in my code where does it happen, but
I should be able to assume that stack trace of the exception will have
at its bottom initial frame of my thread.
The stack trace which I handled doesn't have such, it has only
some .net framwork methods, see my first post.

Also, I still claim that ThreadAbortException should not cause
application crash directly by it self
(by the fact that it was not caught - and moreover was not suppressed
by Thread.ResetAbort()).

Of course it may crash the application indirectly, because of changed
flow, but anyway not ThreadAbortException should by received by
unhandled exceptions event.

zuraff
 
Hi

In .NET 2.0 unhandled exceptions in separate threads cause raising
unhandled exception event and terminating the process. This is true
for most exceptions, but not for ThreadAbortException, what is
reasonable.

I have verified this with following example:
class Program {
private static void thread() {
while (true){}
}
static void Main(string[] args) {
AppDomain.CurrentDomain.UnhandledException
+= new UnhandledExceptionEventHandler(handler);
Thread th = new Thread(new ThreadStart(thread))
th.Start();
Thread.Sleep(5000);
th.Abort();
Thread.Sleep(50000);
}

static void handler(object sender, UnhandledExceptionEventArgs
e) {
System.Console.WriteLine("Unhandled exception.");
}
}

While working with my, quite complex, application, where I must use
Thread.Abort() on one of my threads, I managed to get in the handler
following exception:

Exception: System.Threading.ThreadAbortException
Message: Thread was being aborted.
Source: mscorlib
at System.Reflection.Assembly.GetType(String name, Boolean
throwOnError, Boolean ignoreCase)
at System.Activator.CreateInstanceFrom(String assemblyFile, String
typeName, Boolean ignoreCase,
BindingFlags bindingAttr, Binder binder, Object[] args, CultureInfo
culture, Object[]
activationAttributes, Evidence securityInfo)
at System.AppDomain.CreateInstanceFrom(String assemblyFile, String
typeName)

The application terminated immediately because of that.

This convinced me that in some circumstances ThreadAbortException is
treated just as any other exception and can cause process crash
in .NET 2.0.
The above stack trace is a full stack trace which the exception
conveyed, and looks bit strange for me. My code never use
System.AppDomain.CreateInstanceFrom(..) directly, so I guess this is
some internal mechanism of the framwork/CLR.

Can you think what kind of my code can trigger above one ? It looks
like something related to reflection. What is exact reason that the
ThreadAbortException is not treated just as ThreadAbortException in my
example.

Generally this is very bad news for everyone who use Thread.Abort(),
because there are poor guarantees that the operation does not crash
their application.

PS. Do not suggest me using a flag to stop a thread.

The ThreadAbortException is used to abort the thread while giving the
thread an opportunity to clean up critical data.

The thread should catch the ThreadAbortException, do any neccesary
cleanup, and return from the method.

If possible, Thread.Abort should be avoided. As it stops the thread
whatever if might be doing, it might be difficult to write the cleanup
code so that it can properly handle every possible state that the code
can be in.
 
Thanks Goran

What you says is clear to me.

However I'm looking for the answer for following question: When
ThreadAbortException, when it reaches bottom of stack trace of its
thread causes AppDomain.UnhandledException event and terminating the
application ?

I don't mind illegal state of my code, because of change of the flow
due to Thread.Abort().
 
However I'm looking for the answer for following question: When
ThreadAbortException, when it reaches bottom of stack trace of its
thread causes AppDomain.UnhandledException event and terminating the
application ?

I think you misunderstand the nature of "UnhandledException". It's an
event, not an exception handler.

This has two important implications:

1) It's not running in the thread where the exception occured. That
is, it doesn't "reach the bottom of stack trace of its thread". The
thread has no handler for the exception, and so the thread crashes.

2) It's not *handling* the exception. It's simply giving you notice
that an unhandled exception occurred. This may or may not be a problem
for you, but the fact remains that the exception wasn't ever handled and
if not handling the exception results in instability your entire process
may indeed crash.

If you insist on using Thread.Abort(), then you need to put an exception
handler in the thread itself (that is, try/catch at the top of the thread
*and* make sure that you never abort the thread unless you are 100%
certain that the thread is within the try block). Really, you should not
be using Thread.Abort() at all. But if you insist on doing so, then you
need to handle the exception if you expect for the exception to be handled
properly.

Pete
 
Hi Pete
I think you misunderstand the nature of "UnhandledException". It's an
event, not an exception handler.
I might have called that a handler, but I never thought so. The key is
that once the application is terminating, you can not cancel the
process.
then you need to put an exception
handler in the thread itself (that is, try/catch at the top of the thread
*and* make sure that you never abort the thread unless you are 100%
certain that the thread is within the try block).

So what you suggest is to:

Thread th = new Thread(new ThreadStart(foo)); th.Start();
....
th.Abort();
....

public void foo() {
try {
...
} catch (Exception e)
{...}
}

I understand that you claim that the catch block will prevent from
slipping ThreadAbortException outside foo() if only Abort was called
within try/catch.

That is not actually true, because ThreadAbortException will be
rethrown automatically after leaving catch{} block, provided that
Thread.ResetAbort() was not called before.

But usually, e.g. in my example in the first post, it is okey. CLR
just suppresses that type of exceptions once they slip out of the
thread and process is not terminated. Nothing bad happens.

But for some reason, which I need to discover, some time CLR does not
suppress it and the process IS terminated. Moreover the stack trace
which I managed to log in that case (see my first post) using
UnhandledException event, does not consist my code, and doesn't give
me any chance to add try/catch(){ Thread.ResetAbort();} which will
prevent from slipping it outside.
 
[...]
I understand that you claim that the catch block will prevent from
slipping ThreadAbortException outside foo() if only Abort was called
within try/catch.

That's correct.
That is not actually true, because ThreadAbortException will be
rethrown automatically after leaving catch{} block, provided that
Thread.ResetAbort() was not called before.

This statement has very little to do with the previous. I never suggested
that including an exception handler would prevent the thread from being
aborted. I am only pointing out that if you want to catch the exception,
you have to have some code that it set up to catch exceptions.
[...]
But for some reason, which I need to discover, some time CLR does not
suppress it and the process IS terminated.

You can try to figure that issue out if you like. However, the
fundamental nature of what you're doing is so wrong in the first place,
it's my opinion that what you really ought to be doing is fixing your
design so that you don't rely on the behavior of Thread.Abort() in the
first place.
Moreover the stack trace
which I managed to log in that case (see my first post) using
UnhandledException event, does not consist my code, and doesn't give
me any chance to add try/catch(){ Thread.ResetAbort();} which will
prevent from slipping it outside.

That suggests to me that by aborting your thread, you are somehow screwing
up some other thread. How that might happen, I don't know, and I can't
rule out the possibility of a .NET bug. Still, since you're not
exercising good thread-management behavior in the first place, it's hard
to work up much interest in figuring out your problem for you.

I realize you started out telling us all (in effect) to not tell you to
not use Thread.Abort(). But really, that's the best advice anyone could
give you.

Pete
 
Back
Top