Search code examples
pythonpython-3.xmultithreadingubuntupython-multithreading

Does a Python Stoppable Thread needs to be Daemonized or be .join()?


When using a class Pup for creating stoppable threads that are meant to be running in the background until .stop() is called:

  1. 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()
    
  2. 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()

Solution

  • The StoppableThread should be joined.

    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.

    1. A leak is possible only if your code is responsible for checking the 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.
    2. Taking all of the above into consideration, i think that making StoppableThread as daemon is bad idea.