Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python - Catching signals between sleep calls

So, lets say I have this code:

import signal
from time import sleep

def signalHandler(sig, frame):
    print "signalHandler"
    while True:
        sleep(1)
        #print "Caught" # Uncomment this line, and you get multiple signals - commented, you don't.

signal.signal(signal.SIGINT, signalHandler)
while True:
    sleep(1)

As seen in the comment, if the print statement is uncommented, the code works normally, and the signal handler will catch any subsequent CTRL-C presses like it should. However, if left commented, another signal will never be caught.

Why is this? My guess is that consecutive sleep calls are mashed together, and control is never coming back up to python to catch a signal. Which it would have to do for a print statement. Can anyone shed any insight into this?

like image 626
westem Avatar asked Jun 27 '15 14:06

westem


1 Answers

This is indeed strange!

I believe this is a subtle interaction between the internals of the Python generated bytecode and an anomaly present in Python 2.7 before. Note two things:

  • Your code works perfectly in Python 3 with or without the print statement.
  • If you change the sleep inside the signal handler to "sleep(60)" you'll notice that it still works correctly if you hit Ctrl-C before the print is even reached! (This is what made me suspicious).

If you read Issue 12472 in the Python bug tracker, you'll see that Python inserts an internal call to Py_CheckSleep before the next instruction (in this case, your print), which causes the signal to be caught when the sleep is interrupted. Without the print, the extra check does not occur.

According to the issue, this was fixed in Python 3 and greater, but not in earlier versions.

like image 116
Gary Wisniewski Avatar answered Oct 23 '22 04:10

Gary Wisniewski