Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Closing all threads with a keyboard interrupt

What I'm trying to do here is use a keyboard interrupt to exit all ongoing threads in the program. This is a pared down version of my code where the thread is created:

for i in taskDictionary:     try:         sleep(60)         thread = Thread(target = mainModule.executeThread)         thread.start()     except KeyboardInterrupt:         thread.__stop() 

The program itself is far more complicated, accounting for tons of different variables that affect the threads and even having the option to launch in a sequential mode, where tasks are not threaded, but instead launched one-by-one so there might be some problems with this small variation I just conjured up. I have done this in ways that produced 50/50 results. The interrupts would work but the threads would never cleanly exit. Sometimes they would keep going but halt the execution of future threads, some times they would exit with a massive error regarding the interrupt, other times the interrupts would do nothing at all. Last time I ran this the program stopped any future threads from executing but did not stop the current thread. Is there any way to exit the threads without going into the module the thread is actually executing in?

like image 860
Joe Avatar asked Jul 11 '12 15:07

Joe


People also ask

What is the KeyboardInterrupt?

In computing, keyboard interrupt may refer to: A special case of signal (computing), a condition (often implemented as an exception) usually generated by the keyboard in the text user interface. A hardware interrupt generated when a key is pressed or released, see keyboard controller (computing)

How do I interrupt my keyboard?

The KeyboardInterrupt error occurs when a user manually tries to halt the running program by using the Ctrl + C or Ctrl + Z commands or by interrupting the kernel in the case of Jupyter Notebook. To prevent the unintended use of KeyboardInterrupt that often occurs, we can use exception handling in Python.

How do I stop a while loop in a thread?

Create a Queue from Queue import Queue and pass it to the thread func. Inside the while loop read from the queue (using get ). The main body of the code should put something in the queue that will flag the thread to stop.


2 Answers

A similar question is "How do you kill a thread?"

You create an exit handler in your thread that is controlled by a lock or event object from the threading module. You then simply remove the lock or signal the event object. This informs the thread it should stop processing and exit gracefully. After signaling the thread in your main program, the only thing left to do is to use the thread.join() method in main which will wait for the thread to shut down.

A short example:

import threading import time  def timed_output(name, delay, run_event):     while run_event.is_set():         time.sleep(delay)         print name,": New Message!"   def main():     run_event = threading.Event()     run_event.set()     d1 = 1     t1 = threading.Thread(target = timed_output, args = ("bob",d1,run_event))      d2 = 2     t2 = threading.Thread(target = timed_output, args = ("paul",d2,run_event))      t1.start()     time.sleep(.5)     t2.start()      try:         while 1:             time.sleep(.1)     except KeyboardInterrupt:         print "attempting to close threads. Max wait =",max(d1,d2)         run_event.clear()         t1.join()         t2.join()         print "threads successfully closed"  if __name__ == '__main__':     main() 

If you REALLY need the functionality of killing a thread, use multiprocessing. It allows you to send SIGTERMs to individual "processes" (it's also very similar to the threading module). Generally speaking, threading is for when you are IO-bound, and multiprocessing is for when you are truly processor-bound.

like image 141
Paul Seeb Avatar answered Sep 24 '22 02:09

Paul Seeb


There are a couple of options that don't require using locks or other signals between threads. One is setting the threads as daemons, which will be killed off automatically when the main thread exits. The other is using processes instead, which have a terminate method you can call from the main process, if you needed to kill them and keep the main program running.

Both of these are especially useful if you have threads blocking on input. While using a timeout and periodically checking the signal would work in most cases without too much overhead, using daemons or processes eliminates the need for any busy loops or significant added complexity.

See the answers to this question for more details on these solutions and discussion on the problem of killing threads.

like image 31
Scott Yeager Avatar answered Sep 21 '22 02:09

Scott Yeager