Over a million developers have joined DZone.
Platinum Partner

Dawn Of The Thread

· DevOps Zone

The DevOps Zone is brought to you in partnership with Librato.  Check out Librato's whitepaper on Selecting a Cloud Monitoring Solution.

In my previous post, Night of the Living Thread, I described how a dead Python thread may think it's still alive after a fork, and how I fixed this bug in the Python standard library. But what if you need to save your code from the ravenous undead in Python 2.6? The bug will never be fixed in Python 2.6's standard library. You're on your own. In Python 2.6, no one can hear you scream.

Recall from my last post that I can create a zombie thread like this:

t = threading.Thread()
if os.fork() == 0:
    # We're in the child process.
    print t.isAlive()

isAlive() should always be False, but sometimes it's True. The problem is, I might fork before the thread has added itself to the global _active list, so Python doesn't mark the thread as "stopped" after the fork. To fix this, I need t.start() to wait until the thread is completely initialized, so that I can't fork too soon.

Here's my solution, a SafeThread that will never rise from its grave:

class SafeThread(threading.Thread):
    def __init__(self, *args, **kwargs):
        super(SafeThread, self).__init__(*args, **kwargs)
        self.really_started = threading.Event()

    def start(self):
        super(SafeThread, self).start()

    def run(self):
        super(SafeThread, self).run()

I create an event in the SafeThread's constructor. Then in SafeThread.start(), I call the standard Thread's start method, but I wait for the event before returning. Finally, I trigger the event in run(), which is executed in the new thread. By the time the standard Thread executes run(), it has added itself to _active: thus, we know it's safe to set the event and unblock the thread that called start(). Even if I fork immediately after that, the Safethread is in _active and can't become zombified.

You can imagine more complex scenarios that will still defeat me. For example, Thread A could start Thread B, and Thread C could fork at the wrong moment and leave Thread B zombified. For absolute safety from zombies, upgrade to Python 2.7.6 or 3.3.3 when they're released with my bugfix. Meanwhile, SafeThread is good enough for the common case where the main thread creates the background thread and then forks.

(Get ready for the gory finale, Day of the Thread, in which humanity's last hope is to figure out the quirky code review system used by the Python Software Foundation.)


Published at DZone with permission of A. Jesse Jiryu Davis , DZone MVB .

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}