Is there any way to wait for termination of a thread, but still intercept signals?
Consider the following C program:
I know I'm a bit late to the party, but I came to this question hoping for a better answer than joining with a timeout, which I was already doing. In the end I cooked something up that may or may not be a horrible bastardisation of signals, but it involves using signal.pause() instead of Thread.join() and signalling the current process when the thread reaches the end of its execution:
import signal, os, time, sys, threading, random
threadcount = 200
threadlock = threading.Lock()
pid = os.getpid()
sigchld_count = 0
def handle_sigterm(signalnum, frame):
print "SIGTERM"
def handle_sigchld(signalnum, frame):
global sigchld_count
sigchld_count += 1
def faux_join():
global threadcount, threadlock
threadlock.acquire()
threadcount -= 1
threadlock.release()
os.kill(pid, signal.SIGCHLD)
def thread_doer():
time.sleep(2+(2*random.random()))
faux_join()
if __name__ == '__main__':
signal.signal(signal.SIGCHLD, handle_sigchld)
signal.signal(signal.SIGTERM, handle_sigterm)
print pid
for i in xrange(0, threadcount):
t = threading.Thread(target=thread_doer)
t.start()
while 1:
if threadcount == 0: break
signal.pause()
print "Signal unpaused, thread count %s" % threadcount
print "All threads finished"
print "SIGCHLD handler called %s times" % sigchld_count
If you want to see the SIGTERMs in action, extend the length of the sleep time in thread_doer and issue a kill $pid command from another terminal, where $pid is the pid id printed at the start.
I post this as much in the hope of helping others as being told that this is crazy or has a bug. I'm not sure if the lock on threadcount is still necessary - I put it in there early in my experimentation and thought I should leave it in there in case.