What is a safe way to stop a running thread?
Asked Answered
D

2

10

I have a thread which contains execution of an IronPython script. For some reason I may need to stop this thread at any time, including script execution. How to achieve this? The first idea is Thread.Abort(), but it's known to be evil...

Deadhead answered 14/2, 2012 at 5:50 Comment(5)
Yes, jerking the rug out from under a thread is evil. But if that's what you want to do, then Thread.Abort() is the way to go. The better solution is to modify your application's design.Nullity
Does your thread loop or is it only run for the execution of a single script and then die?Nyctophobia
It loops, but each iteration contains script execution, which can be rather long.Deadhead
@CodyGray, what exactly do you mean by modifying design?Deadhead
So that you don't "need to stop [the] thread at any time". There really isn't enough context provided in the question for me to give any more specific advice. My point is that you're right about Thread.Abort not being ideal, but it's not that function that's evil, it's what it's doing. And since it's doing precisely what you want...Nullity
G
5

Well from you question and subsequent comments I can suggest you two options, with some additional "warnings":

  1. If your thread loops executing something on each iteration, you can set a volatile boolean flag such that it exits after finishing the current iteration (pseudocode because I'm not familiar with python):

    while shouldExit = false
        // do stuff
    

    Then just set the flag to true when you want the thread to stop and it will stop the next time it checks the condition.

  2. If you cannot wait for the iteration to finish and need to stop it immediately, you could go for Thread.Abort, but make absolutely sure that there is no way you can leave open file handles, sockets, locks or anything else like this in an inconsistent state.

Gaul answered 14/2, 2012 at 8:55 Comment(6)
The first solution is obvious, but it's not for my case. I was afraid of using Thread.Abort(), because everywhere people write something like "NEVER USE IT!!!"))). But now I use it in the program - ho handles may stay opened.Deadhead
It is true that most of the time it's bad, but specifically because people tend to use threads for I/O or other things like this that will be left in an inconsistent state if the thread is killed. If you are not using the thread for anything like this then it's perfectly safe.Gaul
And is it guaranteed, that thread with code like this try { // do work - no try/catches here } catch(ThreadAbortException) { // log exit } will be stopped after calling Abort() on it?Deadhead
Unless you are blocked in some I/O inside the try, it should work properly.Gaul
@chersanya: Absolutely not. That is in no way guaranteed. In particular, if you have hostile code running in the thread you are attempting to abort then you have already lost; hostile code can ignore a thread abort. Aborting a thread should be thought of as a strongly worded suggestion to the thread that it go away; a thread that is hostile to that intent can ignore it at its whim if it is cleverly written.Prussiate
@Tudor: To expand on your excellent point: you know what's worse than leaving a file handle open? Closing a file handle when only half the user's data has been buffered out, leaving the document in a broken state such that none of the user's data is recoverable. Similarly with locks; leaving a monitor in the entered state is bad. Exiting a monitor before the code that finishes the protected edit to crucial user data is even worse. People act like aborting threads is bad because it leaves handles allocated, but the actual problem is that it often frees them too early.Prussiate
P
19

What is a safe way to stop a running thread?

Put the thread in its own process. When you want it to stop, kill the process.

That is the only safe way to kill a thread. Aborting a thread can severely destabilize a process and lose user data. There's no way to avoid the "lose user data" scenario if you really, truly need to be able to kill a thread that could be doing anything. The only way to avoid destabilizing the process that is calling for the abort is to make them different processes entirely.

Prussiate answered 14/2, 2012 at 14:53 Comment(6)
In my case there is no way for the thread code to destabilize the whole process. But for common knowledge - by creating different processes you mean having two projects that are compiled to different assemblies and one of them runs another? Or what?Deadhead
@chersanya: You seem awfully sure of yourself. You're running a script; how do you know that the author of the script has not put code in there that will destabilize the process or lose user data when interrupted?Prussiate
@chersanya different processes don't necessarily need to be running different assemblies. For example, myprogram.exe could start a new process running myprogram.exe.Inadvisable
@Eric, that may be true, but there is also a downside there. Generally speaking you don't want to just go around killing processes. Rather you want send them a signal or message telling them to stop. That is rather important if the process is managing some reasource, so it can restore the resource to a consistant state. For some resources (like file locks, or semaphores) the OS can resotre them (possibly exposing some other resource in an inconsistant state), but not all and the side effects are generally undesireable.Zymolysis
To make that fit in with your suggestion, send a message to the new process, which has an "extra" thread that simply looks for the message, does whatever it can to make resources consistant, and then brings down its own process, which inheriently stops the other threads running in it.Zymolysis
@KevinCathcart: Well, sure. But if you have the ability to control the process politely then surely you also have the ability to control a thread politely. If you can build a control system then by all means do so; I understood the question to be "but what do I do if I cannot control the code but nevertheless I want it to stop, right now?"Prussiate
G
5

Well from you question and subsequent comments I can suggest you two options, with some additional "warnings":

  1. If your thread loops executing something on each iteration, you can set a volatile boolean flag such that it exits after finishing the current iteration (pseudocode because I'm not familiar with python):

    while shouldExit = false
        // do stuff
    

    Then just set the flag to true when you want the thread to stop and it will stop the next time it checks the condition.

  2. If you cannot wait for the iteration to finish and need to stop it immediately, you could go for Thread.Abort, but make absolutely sure that there is no way you can leave open file handles, sockets, locks or anything else like this in an inconsistent state.

Gaul answered 14/2, 2012 at 8:55 Comment(6)
The first solution is obvious, but it's not for my case. I was afraid of using Thread.Abort(), because everywhere people write something like "NEVER USE IT!!!"))). But now I use it in the program - ho handles may stay opened.Deadhead
It is true that most of the time it's bad, but specifically because people tend to use threads for I/O or other things like this that will be left in an inconsistent state if the thread is killed. If you are not using the thread for anything like this then it's perfectly safe.Gaul
And is it guaranteed, that thread with code like this try { // do work - no try/catches here } catch(ThreadAbortException) { // log exit } will be stopped after calling Abort() on it?Deadhead
Unless you are blocked in some I/O inside the try, it should work properly.Gaul
@chersanya: Absolutely not. That is in no way guaranteed. In particular, if you have hostile code running in the thread you are attempting to abort then you have already lost; hostile code can ignore a thread abort. Aborting a thread should be thought of as a strongly worded suggestion to the thread that it go away; a thread that is hostile to that intent can ignore it at its whim if it is cleverly written.Prussiate
@Tudor: To expand on your excellent point: you know what's worse than leaving a file handle open? Closing a file handle when only half the user's data has been buffered out, leaving the document in a broken state such that none of the user's data is recoverable. Similarly with locks; leaving a monitor in the entered state is bad. Exiting a monitor before the code that finishes the protected edit to crucial user data is even worse. People act like aborting threads is bad because it leaves handles allocated, but the actual problem is that it often frees them too early.Prussiate

© 2022 - 2024 — McMap. All rights reserved.