Search code examples
pythonmultithreadingpyqtpython-multithreadingqthread

What is Dummy in threading.current_thread()?


I am trying to understand the code in this How to use QThread correctly in pyqt with moveToThread()?

The portion that has:

mainwin.__init__         : MainThread, 140221684574016,
GenericWorker.__init__   : MainThread, 140221684574016,
GenericWorker.run        : Dummy-1, 140221265458944,
mainwin.addBatch         : Dummy-1, 140221265458944,
mainwin.add              : Dummy-1, 140221265458944,
mainwin.add              : Dummy-1, 140221265458944,
mainwin.add              : Dummy-1, 140221265458944,
mainwin.add              : Dummy-1, 140221265458944,
mainwin.add              : Dummy-1, 140221265458944,
mainwin.add              : Dummy-1, 140221265458944

is of interest to me, what are the Dummy -1 elements exactly, my understanding is that these are worker threads doing a job, but will they remain "alive" for ever? or will they be garbage collected on their own. If add batch was done 10k times would the code output have 10k Dummy-1 items? I only ask because I have seen similar output when using subclassed Qthreads, (using Pydev in Eclispe while running code in debug mode).

I am not sure if this means some kind of leak (a thread leak) that would eventually consume lots and lots of resource.


Solution

  • The QThread is not a thread of Qt, but is a class that serves to handle the native threads of each OS how does the threading module of python, and this is mentioned in the docs:

    The QThread class provides a platform-independent way to manage threads.

    So when using threading.current_thread() python tries to get the native thread but as the docs point out (and you can also see it in the source code):

    Return the current Thread object, corresponding to the caller’s thread of control. If the caller’s thread of control was not created through the threading module, a dummy thread object with limited functionality is returned.

    because the QThread created a thread that is not handled by the threading module this will return a dummy thread that represents the thread.

    These are stored in the dictionary inside the threading module so they will not be deleted with GC and they are not a leak. This is mentioned in the docs:

    There is the possibility that “dummy thread objects” are created. These are thread objects corresponding to “alien threads”, which are threads of control started outside the threading module, such as directly from C code. Dummy thread objects have limited functionality; they are always considered alive and daemonic, and cannot be join()ed. They are never deleted, since it is impossible to detect the termination of alien threads.

    And in the source code:

    # Dummy thread class to represent threads not started here.
    # These aren't garbage collected when they die, nor can they be waited for.
    # If they invoke anything in threading.py that calls current_thread(), they
    # leave an entry in the _active dict forever after.
    # Their purpose is to return *something* from current_thread().
    # They are marked as daemon threads so we won't wait for them
    # when we exit (conform previous semantics).
    

    So in conclusion are fictitious elements that provides information on threads not handled by threading, these are not affected by the GC since they are stored in a dictionary and therefore are not a memory leak.