.NET Forum / .NET Framework / New Users / April 2007
Thread Abort and Unhandled Exception Event
|
|
Thread rating:  |
pawel.kedzior@gmail.com - 18 Apr 2007 08:16 GMT 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.
Michael Nemtsev - 18 Apr 2007 09:44 GMT Hello pawel.kedzior@gmail.com,
> 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-6ca 6992460ca
--- 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
pawel.kedzior@gmail.com - 18 Apr 2007 13:08 GMT 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
Göran Andersson - 18 Apr 2007 13:31 GMT > Hi > [quoted text clipped - 61 lines] > > 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.
 Signature Göran Andersson _____ http://www.guffa.com
pawel.kedzior@gmail.com - 18 Apr 2007 19:29 GMT 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().
Peter Duniho - 18 Apr 2007 19:51 GMT > 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
pawel.kedzior@gmail.com - 18 Apr 2007 20:55 GMT 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.
Peter Duniho - 18 Apr 2007 23:50 GMT > [...] > 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
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|