Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

signal.alarm not triggering exception on time

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?

like image 410
Juicy Avatar asked Jan 19 '16 13:01

Juicy


People also ask

What is signal pause?

signal. pause () Cause the process to sleep until a signal is received; the appropriate handler will then be called. Returns nothing. Availability: Unix.

What is SIGUSR1 in Python?

10 (SIGUSR1): user-defined signal. 11 (SIGSEGV): segmentation fault due to illegal access of a memory segment. 12 (SIGUSR2): user-defined signal. 13 (SIGPIPE): writing into a pipe, and nobody is reading from it. 14 (SIGALRM): the timer terminated (alarm)

What is Sigterm in Python?

Python provides the Signal library allowing developers to catch Unix signals and set handlers for asynchronous events. For example, the 'SIGTERM' (Terminate) signal is received when issuing a 'kill' command for a given Unix process.


1 Answers

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').

like image 86
jfs Avatar answered Sep 22 '22 12:09

jfs