When using a class Pup
for creating stoppable threads that are meant to be running in the background until .stop()
is called:
What happens when pup.join()
is not called after pup.stop()
? Will the following result in a leak:
pup = Pup()
pup.start()
time.sleep(5)
pup.stop()
pup2 = Pup()
pup2.start()
time.sleep(5)
pup2.stop()
pup3 = Pup()
pup3.start()
time.sleep(5)
pup3.stop()
Must pup
be a daemonized thread since we are running it in the background?
Main code below is borrowed from this SO answer
import time
import threading
class StoppableThread(threading.Thread):
"""Thread class with a stop() method. The thread itself has to check
regularly for the stopped() condition."""
def __init__(self, *args, **kwargs):
super(StoppableThread, self).__init__(*args, **kwargs)
self._stopper = threading.Event()
def stop(self):
self._stopper.set()
def stopped(self):
return self._stopper.isSet()
class Pup(StoppableThread):
def __init__(self, i, *args, **kwargs):
super(Pup, self).__init__(*args, **kwargs)
self.i = i
def run(self):
while True:
if self.stopped():
return
print("Hello, world!", i)
time.sleep(1)
for i in range(100):
pup = Pup(i)
pup.start()
time.sleep(5)
pup.stop()
The StoppableThread
should be join
ed.
Because it is just a thin wrapper about threading.Thread
giving you a possibility of setting and checking flag stopper
.
In this case, there must be a code that regularly checks this flag. The amount of delay between checks depends on the user of the class.
And given the fact that it is assumed that the thread should be correctly stopped, you must use join
. Because if you make the thread as daemon
and try to stop it before the application finishing:
Daemon threads are abruptly stopped at shutdown. Their resources (such as open files, database transactions, etc.) may not be released properly. If you want your threads to stop gracefully, make them non-daemonic and use a suitable signalling mechanism such as an Event.
stopper
flag and subsequent exiting from the thread does not work correctly. Otherwise, there is no leaks, because the app, even join
is not called, will wait for the completion of all non-daemon threads. But using join
will give more control over the program flow.StoppableThread
as daemon
is bad idea.