import threading import time import os import atexit import signal def run(label): for i in range(1, 10): sl = .5 print("IN THREAD:", label, ", elapsed:", str(i*sl)) time.sleep(sl) def start(procName): tl = [] for j in range(1,5): label = procName + ", thread# " + str(j) t = threading.Thread(target=run, args=(label,)) t.daemon = False t.start() tl.append(t) return tl def join(tl): for t in tl: t.join() def runFork(): pid = os.fork() if pid: print("PARENT FORKING THREAD", "IS" if threading.currentThread().daemon == True else "IS NOT", "DAEMON!") tl = start("Parent, pid: " + str(os.getpid())) os.waitpid(pid, 0) else: print("CHILD MAIN THREAD", "IS" if threading.currentThread().daemon == True else "IS NOT", "DAEMON!") tl = start("Child, pid: " + str(os.getpid())) t = threading.Thread(target=lambda: time.sleep(3600)) t.daemon = True t.start() #os._exit(0) # Uncomment to exit without SIGCHLD join(tl) def handleExit(): print("PID:", os.getpid(), "EXITING!") def handleChildExit(arg1, arg2): print("PID:", os.getpid(), "CHILD EXITING!") def main(): signal.signal(signal.SIGCHLD, handleChildExit) atexit.register(handleExit) if True: # Change to False to run from main thread and get parent signaled when child is done. t = threading.Thread(target=runFork) t.daemon = False t.start() t.join() else: runFork() if __name__ == "__main__": main()