signal.alarm not triggering exception on time

2019-05-02 20:29发布

问题:

I've slightly modified the signal example from the official docs (bottom of page).

I'm calling sleep 10 but I would like an alarm to be raised after 1 second. When I run the following snippet it takes way more than 1 second to trigger the exception (I think it runs the full 10 seconds).

import signal, os

def handler(signum, frame):
    print 'Interrupted', signum
    raise IOError("Should after 1 second")

signal.signal(signal.SIGALRM, handler)
signal.alarm(1)

os.system('sleep 10')

signal.alarm(0)

How can I be sure to terminate a function after a timeout in a single-threaded application?

回答1:

From the docs:

A Python signal handler does not get executed inside the low-level (C) signal handler. Instead, the low-level signal handler sets a flag which tells the virtual machine to execute the corresponding Python signal handler at a later point(for example at the next bytecode instruction).

Therefore, a signal such as that generated by signal.alarm() can't terminate a function after a timeout in some cases. Either the function should cooperate by allowing other Python code to run (e.g., by calling PyErr_CheckSignals() periodically in C code) or you should use a separate process, to terminate the function in time.

Your case can be fixed if you use subprocess.check_call('sleep 10'.split()) instead of os.system('sleep 10').