I've inherited some service code and I'm trying to track down an issue with service crashes. I've found the following code in many places:
catch (ThreadAbortException)
{
throw;
}
However, I can't find any calls to Thread.Abort() or Thread.Kill() in any parts of the project (or related projects).
Is Thread.Abort() ever implicitly called by the .NET runtime, or does that exception exist only to catch calls that a developer makes? I'm trying to narrow my error avenues and I'm not very experienced with threads in C#. I'm trying to determine whether the catch block I've shown is ever actually hit if Thread.Abort() is never actually called in my codebase.
Thanks!
Edit: I want to clarify - I know that .NET can kill threads, but I was wondering if it specifically calls Thread.Abort() or whether it uses some other means (as the ThreadAbortException is only called on Thread.Abort().
Catch/throw without doing anything about it seems pointless.
These errors are common in ASP.NET-- it means a redirect that ended the response, eg. ASP.NET Response.Redirect( ) Error
or it means a worker process was killed by casinni/iis/aspnet for it's own mysterious reasons, maybe worker process recycles, etc.
It normally doesn't indicate a programming error.
Calling Thread.Abort() in multi-threaded apps appears to be a bad idea in most cases and other answers on SO speak to that better than I could.
Edit: I want to clarify - I know that .NET can kill threads, but I was
wondering if it specifically calls Thread.Abort() or whether it uses
some other means (as the ThreadAbortException is only called on
Thread.Abort().
If you're really interested to see whether (and where) it does that, refer to .NET Reference Source, it's pretty complete. Specifically, it shows that Thread.Abort is referenced at these places.
Related
I happened to lay my eyes on an intellisense tool tip regarding the parameter passed to System.Threading.Thread.Sleep(int millisecondsTimeout), saying something like "(…) Specify System.Threading.Timeout.Infinite to block the thread indefinitely". And I am intrigued.
I can understand why one might include short inactive delays within a possibly endless loop, thus yielding processing power to other executing threads when no immediate action in the sleeping thread is required, although I typically prefer implementing such delays with EventWaitHandlers so that I can avoid waiting a full sleeping delay if I signal the thread to gracefully end its execution from a different thread.
But I cannot see when I might need to suspend a thread indefinitely, and in a way that, as far as I can tell, can only be interrupted through a rather ungraceful Thread.Abort()/ThreadAbortException pair.
So what would be a working scenario where I might want to suspend a thread indefinitely?
It is a pretty long story and I have to wave my hands a bit to make it understandable. Most programmers think that Thread.Sleep() puts the thread to sleep and prevents it from executing any code. This is not accurate. Thread.Sleep(Infinite) is equivalent to Application.Run(). No kidding.
This doesn't happen very often in real life, it is mostly relevant in custom hosting scenarios. Getting code to run on a specific thread is in general an important feature to deal with code that is not thread-safe and the major reason why Application.Run() exists. But Windows exposes another way to do at a much lower level, the underlying api for this is QueueUserAPC(). The .NET analogue of this function is BeginInvoke().
This requires the thread to co-operate, just like it does when it calls Application.Run(). The thread must be in an "alertable wait state", executing a blocking function that can be interrupted. The CLR does not execute the sleep by itself, it passes the job to the CLR host. Most hosts will simply execute SleepEx(), passing TRUE for the bAlertable argument. The thread is now in a state to execute any requests posted by QueueUserAPC(). Just like it will be when it is actively executing inside the Application.Run() dispatcher loop.
The kernel feature is not otherwise exposed at all in the framework. It is the kind of code that is very hard to get right, re-entrancy bugs are pretty nasty. As most programmers that were bitten by Application.DoEvents() or a poorly placed MessageBox.Show() can attest. It is however a valid scenario in a custom hosting scenario. Where the host can get C# code to run on a specific thread, using this mechanism. So it is possible to pass Infinite because the designers did not want to intentionally disable this scenario. If this is made possible at all by the host author then they'd let you know about it. I don't know of a practical example.
More practically, you do use this feature every day. It is the way that System.Threading.Timer and System.Timers.Timer are implemented. Done by a thread inside the CLR which is started as soon as you use any timer, it uses SleepEx(INFINITE, TRUE) at its core.
You can use .Interrupt() to wake a sleeping thread (causing ThreadInterruptedException in the code that was calling .Sleep(), which can be caught and handled), so this provides a mechanism to say "sleep until someone prods you". I'm not saying it is necessarily the best mechanism for this, but: it may have uses for you.
I'm working in a legacy project that has this exception handling code in many methods.
catch(ThreadAbortException e)
{
...
}
I don't see anywhere in the project Thread.Abort() or Thread.Interrupt() calls. Is it safe to delete all these ThreadAbortException handling or it is some other way that can be raised.
Well if answering specifically your question I would say that it would be better not to delete these exception handlers as it’s most likely that they were added by some developer trying to solve a problem. And I think there was a reason to add those handlers so if you just remove this code it can lead to appearing of some bugs again in the future.
Regarding the ThreadAbordException: I know for sure that it can be throwed not only with calling Thread.Abort() method when you are debugging (it might be a bug in VS, I’m not sure) and it forces your program to just crash silently. So depending on what’s inside of those handlers it could be possible that a developer was trying to solve such problem.
Also remember that you could be invoking methods of third-party libraries, web-services etc. in a separate thread, too. I’m not sure if they can throw such an exception but that’s a possible case to consider.
Official docs: "The exception that is thrown when a call is made to the Abort method." If you are completely sure there are no calls to Thread.Abort then you might as well erase those catch blocks.
EDIT: Be mindful that your code may be running in the context of an external app that may call Thread.Abort on your threads.
Not that it matters anyway as a ThreadAbortException can't really be handled as the CLR itself will rethrow it to actually kill the thread ASAP.
"Actually yes, a ThreadAbortException is special. Even if you handle it, it will be automatically re-thrown by the CLR at the end of the try/catch/finally. (As noted in the comments, it can be suppressed with ResetAbort but by that point the code smells like rotten fish.)"
- Read this question for more details: ThreadAbortException
Is the project running on a main thread and spinning up background worker threads? If the main thread exits while background threads are running, a ThreadAbortedException can occur on the background threads.
The catch statement could specifically handle this scenario, where no error actually occurred on the background thread, in a different manner than any other exception.
I have a situation on a production machine where a thread in my Windows Service appears simply to die, without throwing an exception. To date my logging hasn't been verbose enough to pinpoint the exact line of code where it is dying; I've deployed a new version with more verbose logging for this purpose. But until I get a smoking gun, my suspicion falls on the line of code where I create a new DB context.
The error is not predictable, except that it tends to happen during periods of high activity, and is often correlated with other threads throwing DB timeout exceptions (hence my suspicion above). Exceptions I can handle. Dead threads I can't.
Any ideas why a thread might die silently, or otherwise simply freeze? Or what to do about it?
EDIT: To be clear, the code is surrounded by a try-catch block, and the catch does some logging (using log4net). So does the "finally". I know it's working because other threads have left logs when they threw exceptions. All that I see in my log is that thread x hits a certain debug point, then is never seen or heard from again, and the work it was supposed to do remains not done.
No, not really (but kind of). Threads don't die, they finish. A thread can finish successfully or by failure--if a thread fails then its exception is stored until it is handled. Depending on how you instantiate the thread it's possible that you "fire and forget", meaning that if an exception occurs you have no code to handle and retrieve it. This is doubly bad, as it results in unreleased resources (they're waiting for you to retrieve and handle the exception).
However, you haven't provided any details of what you've diagnosed. What threading approach/framework are you using (there's quite a few)? Are you watching the processes threads and seeing it suddenly disappear? Are you taking heap snapshots, or attaching to the running process after it appears to have died?
If you have access to the system i would debug it with: Visual Studio 2013 Remote Debugger. This is often a good choice if you can't reproduce the error in your development environment.
Threads do not silently freeze or crash, check whether you have some empty catch blocks in your code or it runs into an infinite loop (or very long timeout at any point).
Maybe you have some code for us.
Recently I worked with an external dll library where I have no influence on it.
Under some special circumstances, a method of this third party dll is blocking and never returning.
I tried to work around this issue by executing this method in a new AppDomain. After a custom timeout, I wanted to Unload the AppDomain and kill all this crap ;)
Unfortunately, it does not work - as someone would expect.
After some time it throws CannotUnloadAppDomainException since the blocking method does not allow aborting the thread gracefully.
I depend on using this library and it does not seem that there will be an update soon.
So can I work around this issue, even if it's not best practice?
Any bad hack appreciated :)
An AppDomain cannot typically solve that problem, it's only good to throw away the state of your program. The real issue is that your thread is stuck. In cases like these, calling Thread.Abort() is unlikely to work, it will just get stuck as well. A thread can only be aborted if it is a "alertable wait state", blocking on a CLR synchronization object. Or executing managed code. In a state that the CLR knows how to safely clean up. Most 3rd party code falls over like this when executing unmanaged code, no way to ever clean that up in a safe way. A decisive hint that this is the case is AppDomain.Unload failing to get the job done, it can only unload the AppDomain when it can abort the threads that are executing code in the domain.
The only good alternative is to run that code in a separate process. Which you can kill with Process.Kill(). Windows do the cleanup. You'd use a .NET interop mechanism to talk to that code. Like named pipes, sockets, remoting or WCF. Plus the considerable hassle of having to write the code that can detect the timeout, kills the process, starts it back up and recovers internal state since you now restart with an uninitialized instance of that 3rd party code.
Do not forget about the real fix. Create a small repro project that reproduces the problem. When it hangs, create a minidump of the process. Send both to the 3rd party support group.
after reading this (scroll down the end to Blocking Issues) I think your only solution is to run the method in a different process - this might involve quite a bit of refactoring and/or a 'host' project (eg Console application) that loads the method in question and makes it easy to call (eg reading args from command line) when launching the new process using the Process class
You can always use background worker, no need to create a new appdomain. This will ensure that you have complete control over the execution of the thread.
However, there is no way to ensure that you can gracefully abort the thread. As the dll is unmanaged, chances are there that it may cause memory leaks. However, spawning a new thread will ensure that your application does not crash when the Dll does not respond.
I am new to multithreaded application. I have few doubts before starting working on it.
Can anyone clear these doubts?
How to handle exceptions in multithreaded application?
If there is any exceptions in any 1 thread, will the whole application will come
down? or all other threads will continue?
How to handle exceptions in multithreaded application?
The best way is inside the thread, but sometimes eg. (thread pool) this is hard. To handle unhandled exceptions depends on the type of application:
WPF: Use Application.DispatcherUnhandledException
Console or Service: Use AppDomain.UnhandledException
ASP.NET, WinForms, ... have their own mechanisms.
But consider: especially while developing to allow the default handling and falling into the debugger (adding if (Debugger.IsAttached) { Debugger.Break(); } can be very helpful to define a permanant breakpoint
If there is any exceptions in any 1 thread, will the whole application will come down?
It depends. In ASP.NET: No (if debugging is enabled you'll see a Yellow Screen of Death, otherwise a 500 server error result); in other hosts: depends (but generally the answer is Yes the process will terminate).
Some of the details of this have changed between .NET versions – typically getting stricter, so you need to do your research. Finally: in .NET 4 certainly, possibly before as well, certain exceptions (eg. StackOverflowException) cannot be caught because there is no reliable way to have consistent process state if they are thrown.
If you are using TPL you can use Aggregate exception. This aggregate exception is a collection of exceptions you can loop through them to see which thread failed to execute more information can be found here. http://msdn.microsoft.com/en-us/library/dd997415.aspx