Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling Thread.Abort on a thread from a ThreadPool

My co-worker is using a third-party .NET library for which we don't have the source code. We're using a ThreadPool to have a lot of threads call into this library, and occasionally one of the threads will just hang forever while the rest of them merrily chug along.

So we want to use the dreaded Thread.Abort to kill such threads. I've done this before when spinning up my own threads, but I've never used a ThreadPool. If we track the start times of each task like this:

static Dictionary<Thread, DateTime> started = new Dictionary<Thread, DateTime>();

static void DoSomeWork(object foo)
{
    lock(started)
        started[Thread.CurrentThread] = DateTime.Now;

    SomeBuggyLibraryThatMightInfiniteLoopOrSomething.callSomeFunction(doo);

    lock(started)
        started.Remove(Thread.CurrentThread);
}

then can we lock and iterate over the running threads and call Thread.Abort to kill them? And if we do, then will we need to add a new thread to the ThreadPool to replace the one that we just killed, or will the ThreadPool handle that for us?

EDIT: I'm very aware of all of the potential problems with Thread.Abort. I know that it should ideally never be used in production code, and that it doesn't necessarily even stop the thread, and that if you abort a thread while the thread has acquired a lock, then you can hang up other threads, etc. But right now we're on a tight deadline and we have decent reason to believe that in this one particular case, we can call Thread.Abort without putting the entire process in jeopardy, and we'd like to avoid rewriting this program to eliminate the ThreadPool unless we absolutely have to.

So what I want to know is this: given that we WILL be calling Thread.Abort on a thread that belongs to a ThreadPool, are there any special problems caused by these being ThreadPool threads, and do we have to manually spin up a new thread to replace the one that got killed or will the ThreadPool do that for us?

like image 432
Eli Courtwright Avatar asked Feb 25 '10 15:02

Eli Courtwright


People also ask

What will happen if the abort method is called on a thread?

If the thread that calls Abort holds a lock that the aborted thread requires, a deadlock can occur. If Abort is called on a thread that has not been started, the thread will abort when Start is called. If Abort is called on a thread that is blocked or is sleeping, the thread is interrupted and then aborted.

Why is thread abort obsolete?

Abort may prevent the execution of static constructors or the release of managed or unmanaged resources. For this reason, Thread. Abort always throws a PlatformNotSupportedException on .


2 Answers

No, you shouldn't call Abort on threads in the thread pool. From my local testing, it seems that the ThreadPool does recreate threads if you abort them - I aborted 1000 thread pool threads and it was still working. I don't know if you should rely on this behaviour, but maybe you can get away with it in this case. In general though using Thread.Abort is not the right way to do this.

The correct way to call a function you don't trust to behave well is to start it in a new process and kill the process if necessary.

like image 128
Mark Byers Avatar answered Sep 28 '22 09:09

Mark Byers


The use of Thread.Abort is not adviced, because it can leave your application in an invalid state. The reason for this is that when demanding a thread to abort, an exception can be raised in almost any possible place in that 3rd party library. It's possible that there are code segments that aren't written to be able to cope with these asynchronous aborts.

So while it is generally not advised to abort threads, there are hosts that are very aggressive in aborting threads. One of them is ASP.NET. When a request takes too long, it will abort the thread for you. So with this in mind it's silly to say "never abort threads".

I advice you to find out where this code hangs (the stack trace of ThreadAbortException should give you a lot of information). If it always hangs on the same place (it's probably a deadlock), find out with Reflector if aborting a thread at that point will result in some state corruption. With that information you can perhaps already fix the problem (perhaps you lock on a object of that library) or can send a mail to the writer of that library. If this all doesn't help and you see there is not a risk in aborting it, be pragmatic and kill it :-)

However, if there is a change of any state corruption, you should try to go with Mark Byers' answer. That is: try running that library in its own AppDomain. This way you can unload the complete AppDomain and there is no change in it affecting your application.

like image 27
Steven Avatar answered Sep 28 '22 08:09

Steven