What's Wrong With Using Thread.Abort()

What's wrong with using Thread.Abort()

In addition to all of the other good answers here, let me add that there is no guarantee whatsoever that a call to Thread.Abort will actually abort the thread in question, ever. It is possible (though not particularly easy) to "harden" a thread against being aborted. If, for example, you are aborting a thread because you believe it to be running hostile code then the hostile code could be resisting its own destruction.

If you have a long-running operation involving code that you do not own that must be taken down cleanly, the correct way to do this is to put that code in its own process, not its own thread. (And preferably in a highly security-restricted appdomain in that process.) You can then cleanly kill the process.

In short, Thread.Abort is at best indicative of bad design, possibly unreliable, and extremely dangerous. It should be avoided at all costs; the only time you should ever even consider aborting a thread is in some sort of "emergency shutdown" code where you are attempting to tear down an appdomain as cleanly as possible.

Revisiting Thread.Abort() - is it safe?

Thread.Abort is a lot safer than it used to be for the following reasons.

  • The runtime will defer aborts while execution is in unmanaged code.
  • The abort will allow finally blocks to execute.

However, there is still a problem with exactly when the ThreadAbortException gets injected. Consider this code.

public class Example
{
private DateTime value = DateTime.MinValue;

public void DoSomething()
{
try
{
value = DateTime.UtcNow;
}
finally
{
}
}
}

If this code were running on a 32-bit platform the value variable could be corrupted if Thread.Abort was called and the ThreadAbortException were injected in the middle of the write to value. Since DateTime is 8 bytes the write has to take place using more than one instruction.

It is possible to guard against this by placing critical code in a finally block and by using Constrained Execution Regions, but it would be incredibly difficult to get right for all but the simplest types your define. And even then you cannot just put everything in a finally block.

Is using Thread.Abort() and handling ThreadAbortException in .NET safe practice?

Is using Thread.Abort() and handling ThreadAbortException in .NET safe practice?

TL;DR version: No, isn't.

Generally you're safe when all type invariants (whether explicitly stated or not) are actually true. However many methods will break these invariants while running, only to reach a new state when they are again true at the end. If the thread is idle in a state with invariants held you'll be OK, but in that case better to use something like an event to signal the thread to exit gracefully (ie. you don't need to abort).

An out-of-band exception1 thrown in a thread while in such a invariants-not-true, ie. invalid, state is where the problems start. These problems include, but are certainly not limited to, mutually inconsistent field and property values (data structures in an invalid state), locks not exited, and events representing "changes happened" not fired.

In many cases it is possible to deal with these in clean up code (eg. a finally block), but then consider what happens when the out-of-band exception occurs in that clean up code? This leads to clean up code for the clean up code. But then that code is it self vulnerable so you need clean up code for the clean up code of the clean up code… it never ends!

There are solutions, but they are not easy to design (and tends to impact your whole design), and even harder to test—how to re-create all the cases (think combinatorial explosion). Two possible routes are:

  1. Work on copies of state, update the copies and then atomically swap current for new state. If there is an out-of-band exception then the original state remains (and finalisers can clean up the temporary state).

    This is rather like the function of database transactions (albeit RDBMSs work with locks and transaction log files).

    It is also similar to the approaches to achieving the "strong exception guarantee" developed in the C++ community in response to a paper questioning if exceptions could ever be safe (C++ of course has no GC/finaliser queue to clean up discarded objects). See Herb Sutters "Guru of the Week #8: CHALLENGE EDITION: Exception Safety" for the solution.

    In practice this is hard to achieve unless your state can be encapsulated in a single reference.

  2. Look at "Constrained Execution Regions", but not the limitations on what you can do in these cases. (MSDN Magazine had an introductory article (introduction to the subject, not introductory level), from .NET 2 beta period2).

In practice if you have to do this, using approach #2 to manage the state change under #1 is probably the best approach, but getting it right, and then validating that it is correct (and the correctness is maintained) is hard.

Summary: It's a bit like optimisation: rule 1: don't do it; rule 2 (experts only): don't do it unless you have no other option.


1 A ThreadAbortException is not the only such exception.

2 So details have possibly changed.

Why thread.IsAlive - thread.Abort() doesn't works?

So, with all conversations in my post, as well as discussions outside of StackOverflow, I found, that I ask about quite fundamental issue, which haven't any solution is the Microsoft Windows architecture:

When external task started in some thread with API, and it is running, there is no way to cancel this execution, and return it to the initial suspend status, but another API (as "Cancel" in ProgressBar) made specially to return it to the Idle Loop waiting.

In other time sharing OS such a special point exists, but not in Windows.
As a result, when no Cancel API interface described, we should run another thread, possibly, from the tread pool to save CPU time in the system, and keep waiting, until unnecessary one would be completed.

Respond from Tekla developers confirm my conclusion:
"Such methods do not exist. As I wrote before, implementing multi-threading in your app could not improve performance changing colors because TeklaStructures internal code does not use it."

Is C#'s using statement abort-safe?

The book's companion web site has more info on aborting threads here.

In short, the first translation is correct (you can tell by looking at the IL).

The answer to your second question is that there may be scenarios where the variable can be legitimately null. For instance, GetFoo() may return null here, in which you wouldn't want a NullReferenceException thrown in the implicit finally block:

using (var x = GetFoo())
{
...
}

To answer your third question, the only way to make Abort safe (if you're calling Framework code) is to tear down the AppDomain afterward. This is actually a practical solution in many cases (it's exactly what LINQPad does whenever you cancel a running query).

How to use thread.abort()

In case you have to use threads, try this. Otherwise, try cancelAsync like in this link:
https://www.wpf-tutorial.com/misc/cancelling-the-backgroundworker/

     // We will set this true to notify the worker threads return.
private bool shouldAbort;
// when hitting submit set:
shouldAbort = false;
void MethodThatDoesWork()
{
//we should stop if required
if (shouldAbort)
{
state.Stop();
}
//code
}

we must be sure that all threads are terminated when the form is closed.
so we add these controls.

   private void ItemsCopyer_FormClosing(object sender, FormClosingEventArgs e)
{
System.Diagnostics.Process.GetCurrentProcess().Kill();
}

private void btnAbort_Click(object sender, EventArgs e)
{
shouldAbort = true;
btnAbort.Enabled = false;
}

does aborting a thread while in 'using' block dispose used instance

Most likely it will, but you can't be sure.

According to the documentation:

When this method [Abort] is invoked on a thread, the system throws a ThreadAbortException in the thread to abort it.

And we know exceptions will still let using statements dispose, as they should. (Give and take a few exceptions)

On the other hand, if you can end the thread gracefully, for example with a CancellationTokenSource, it would be a lot nicer for your app. It will offer much more control over the actual termination of your thread and the handling of exceptions.



Related Topics



Leave a reply



Submit