#!/usr/bin/env python import os, time, threading def worker(): # Wait just a bit before forking so that the original thread makes it into # my_acquire. time.sleep(0.3) childpid = os.fork() if childpid != 0: # Parent process just waits for child. os.waitpid(childpid, 0) # Child process should just return. w = threading.Thread(target=worker) # Stub out the private condition variable's lock acquire method. There is a # race to acquire this between w.join() and w.__stop(), which is called when the # thread returns. orig_acquire = w._Thread__block.acquire call_count = 0 def my_acquire(): global call_count orig_acquire() if call_count == 0: # Make w.join() take longer between calls to self.__block.acquire() and # self.__block.wait(), which releases the lock. w.__stop() should then # deadlock. time.sleep(1) call_count += 1 w._Thread__block.acquire = my_acquire w.start() w.join()