By writing a little C module I fixed the problem. By simply calling the function in the child thrd's run method, things work as expected.
This is all the function (blockall) does: sigset_t omask, nmask; sigfillset(&nmask); sigprocmask(SIG_SETMASK, &nmask, NULL); bash-2.05b# python2.5 ./thrd_test.py Starting up MainThread.run(): 71799 ChildThread.run(): 71799 ChildThread before sleep(10) MainThread before sleep(15) ^CReceived signal 2 flag: True flag: False MainThread after sleep(15) Shutting down bash-2.05b# Chad > I've run into an "opportunity" in a Python application using threads > and signals. Basically, there is a main process that spawns off a child > thread that loops forever. In between iterations, the child > thread sleeps for X seconds. All the while, the main thread loops > forever doing its thing and also sleeps in between iterations (see the code > at > the end this message). Normally the application would > be daemonized before the main process starts up. Hence, during a > system shutdown or stoppage of the daemon, it's desired that the > daemon catch a few signals (TERM/INT) and perform a few cleanup > routines. According to the Python docs, only the main thread will receive > signals. The problem I have, on FreeBSD systems, is that the sleep > function in the child gets interrupted and the signal never gets handled > until the main thread's sleep concludes. It works as expected on a Linux > box (main thrd's sleep is interrupted). Sample output from multiple systems > is directly below. > > Just looking for insight from others in the know. > > Thanks, > Chad > > > Linux 2.6.17 > ------------------------------------------------------------------------ > test_bed$ python2.5 ./thrd_test.py > Starting up > MainThread.run(): 14332 > MainThread before sleep(15) > ChildThread.run(): 14332 > ChildThread before sleep(10) > Received signal 2 <-- Interrupted here (Ctrl-C), correctly > flag: True interrupts sleep in main thread > flag: False > MainThread after sleep(15) > Shutting down > > test_bed$ python2.4 ./thrd_test.py > Starting up > MainThread.run(): 14338 > MainThread before sleep(15) > ChildThread.run(): 14338 > ChildThread before sleep(10) > Received signal 2 <-- Interrupted here (Ctrl-C), correctly > flag: True interrupts sleep in main thread > flag: False > MainThread after sleep(15) > Shutting down > test_bed$ > > FreeBSD 4.11, 6.1, and 6.2 > ------------------------------------------------------------------------ > bash-2.05b# python2.5 ./thrd_test.py > Starting up > MainThread.run(): 65930 > ChildThread.run(): 65930 > ChildThread before sleep(10) > MainThread before sleep(15) > ^CChildThread after sleep(10) <-- Interrupted here (Ctrl-C), but > ChildThread before sleep(10) interrupts the child thrd's sleep > ChildThread after sleep(10) > ChildThread before sleep(10) > Received signal 2 <-- Main sleep concludes and > then > flag: True the signal gets handled > flag: False > MainThread after sleep(15) > Shutting down > bash-2.05b# > > > #--- CODE BEGIN ---# > > #!/usr/bin/env python > > import os > import sys > import time > import signal > import threading > > def sigHandle(signo, stkframe): > print "Received signal ", signo > print "flag: ", mthrd.flag.isSet() > mthrd.flag.clear() > print "flag: ", mthrd.flag.isSet() > > class ChildThread(threading.Thread): > > def __init__(self): > threading.Thread.__init__(self) > > def run(self): > print "ChildThread.run(): ", os.getpid() mymod.blockall() > while (True): > print "ChildThread before sleep(10)" > time.sleep(10) > print "ChildThread after sleep(10)" > > class MainThread(object): > > def __init__(self): > self.flag = threading.Event() > self.cthrd = ChildThread() > self.cthrd.setDaemon(True) > > def run(self): > print "MainThread.run(): ", os.getpid() > self.flag.wait() > self.cthrd.start() > while (self.flag.isSet()): > print "MainThread before sleep(15)" > time.sleep(15) > print "MainThread after sleep(15)" > return # or cleanup routine > > if __name__ == "__main__": > > # Normally, the process is daemonized first. That's been > # left out for testing purposes. > > signal.signal(signal.SIGINT, sigHandle) > signal.signal(signal.SIGQUIT, sigHandle) > signal.signal(signal.SIGTERM, sigHandle) > > mthrd = MainThread() > print "Starting up" > mthrd.flag.set() > mthrd.run() > print "Shutting down" > > sys.exit(0) > > #--- CODE END ---# -- http://mail.python.org/mailman/listinfo/python-list