Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gracefully Terminating Python Threads

I am trying to write a unix client program that is listening to a socket, stdin, and reading from file descriptors. I assign each of these tasks to an individual thread and have them successfully communicating with the "main" application using synchronized queues and a semaphore. The problem is that when I want to shutdown these child threads they are all blocking on input. Also, the threads cannot register signal handlers in the threads because in Python only the main thread of execution is allowed to do so.

Any suggestions?

like image 630
George Avatar asked Jun 15 '11 14:06

George


People also ask

How do you close a thread in Python gracefully?

First, we can update the task() function to take a threading. Thread instance as an argument and then to check that the event is not set each iteration of the while-loop. Once the event is set, the loop will exit and the background task will report a message that it is terminating gracefully.

How do you stop and start a thread in Python?

Calling the start() function on a terminated thread will result in a RuntimeError indicating that threads can only be started once. Instead, to restart a thread in Python, you must create a new instance of the thread with the same configuration and then call the start() function.

Does thread stop automatically Python?

In computer science, a daemon is a process that runs in the background. Python threading has a more specific meaning for daemon . A daemon thread will shut down immediately when the program exits.


1 Answers

There is no good way to work around this, especially when the thread is blocking.

I had a similar issue ( Python: How to terminate a blocking thread) and the only way I was able to stop my threads was to close the underlying connection. Which resulted in the thread that was blocking to raise and exception and then allowed me to check the stop flag and close.

Example code:

class Example(object):
   def __init__(self):
       self.stop = threading.Event()
       self.connection = Connection()
       self.mythread = Thread(target=self.dowork)
       self.mythread.start()     
   def dowork(self):

        while(not self.stop.is_set()):
             try:
                  blockingcall()        
             except CommunicationException:
                  pass
   def terminate():
       self.stop.set()
       self.connection.close()
       self.mythread.join()

Another thing to note is commonly blocking operations generally offer up a timeout. If you have that option I would consider using it. My last comment is that you could always set the thread to deamonic,

From the pydoc :

A thread can be flagged as a “daemon thread”. The significance of this flag is that the entire Python program exits when only daemon threads are left. The initial value is inherited from the creating thread. The flag can be set through the daemon property.

like image 50
Nix Avatar answered Oct 01 '22 13:10

Nix