2

When running background threads, the common way to stop threads on SIGINT appears to be to either mark them as daemon threads, and just exit the main program, or to set a flag:

import signal
import sys
from threading import Event, Thread

kill_threads = Event()

# Define signal handler
def signal_handler(*args, **kwargs):
    kill_threads.set()
    sys.exit(0)

# Register the signal handler callback function
signal.signal(signal.SIGINT, signal_handler)    

def my_thread():
    while not kill_threads.is_set():
        # Do stuff

Thread(target=my_thread).start()

This works fine, as long as the operation you're doing in your thread is non-blocking. That's not always an option. If you're dealing with an external library that you didn't write, and don't control the source code of, having that library run in a non-blocking way isn't always possible.

If your thread can't check a flag to know when to exit because it's running a blocking function, what's the best way to interrupt it?

John
  • 2,551
  • 3
  • 30
  • 55
  • If you can't control it, you can terminate it less nicely by using `thread.join(timeout=5)`. But usually it is better to promote your thread to a process, and us the `process.terminate()` signal. More things about killing a thread are [here](https://stackoverflow.com/questions/323972/is-there-any-way-to-kill-a-thread) and for processes are [here](https://stackoverflow.com/questions/1359383/run-a-process-and-kill-it-if-it-doesnt-end-within-one-hour) – Thymen Dec 22 '20 at 23:09
  • It sounds like `thread.join(timeout=5)` will try to wait for the thread to complete, but if the thread doesn't complete in 5 seconds, an exception is thrown in your main thread (the one that called `thread.join()`, but the thread keeps running. Or am I wrong? – John Dec 22 '20 at 23:23
  • You are correct, my bad. The thread will continue in the background. In that case I would advice to make it a process, and `terminate` the process when you want it to stop. – Thymen Dec 23 '20 at 11:24
  • If there are no solutions using threading, I might have to use `multiprocessing` as you suggest – John Dec 23 '20 at 15:21
  • I do not know how you process your input, but if you can split up the calls to your external library, you can check the done signal between batches. – Thymen Dec 23 '20 at 16:03
  • @Thymen Each call to the external library can take hours to complete. If it didn't, the code in my question would work perfectly fine in that scenario. – John Dec 23 '20 at 16:28
  • What I meant, is that if you have a lot of data that is send to this library, maybe you could split up the data that was sent to it. Such that the individual calls are shorter, but the full process will still take hours. But without knowing the actual process, this might be a very redundant remark, for example if you are just sending 1 thing. – Thymen Dec 23 '20 at 19:27
  • @Thymen I know what you're saying. There's nothing to split up. Each individual call to the library takes hours to return. What you're describing is a scenario that can be handled by the code in the original question. Clearly, that's not the scenario I'm asking about. – John Dec 23 '20 at 19:44

0 Answers0