I learned just now that only the main thread in python handles signals. Signals are caught and placed in a queue which is checked at the execution of each line of code. So in code like this:
LOG = True
while LOG:
try:
data = myqueue.get()
print data
except (KeyboardInterrupt, SystemExit):
LOG = False
the program will block on the myqueue.get() call and not catch a Ctrl-C until something comes out of the queue. One must instead write it something like this:
LOG = True
while LOG:
try:
data = myqueue.get_nowait()
print data
except (KeyboardInterrupt, SystemExit):
LOG = False
except (Queue.Empty):
continue
Here myqueue.get_nowait() will return immediately
if nothing ins in the queue, raising a Queue.Empty
exception, which I catch and gracefully ignore. Everything would be
hunky-dory except even this code sometimes fails to quit properly
with a Ctrl-C. The resulting traceback seems to focus on the
myqueue.get_nowait() or the except
(Queue.Empty) lines, indicating that the Keyboard Interrupt
was caught in execution of these lines and therefore somehow not
caught by the try statement. Why it’s not caught by the try
statement I'm not sure yet.