Reputation: 13914
I am trying to implement a function that will timeout if it fails to complete in a certain amount of time (having issues with a thread hanging). This answer seemed the most promising, effectively providing an API wrapper with which to call my actual function. It generally seems to work (see loop_forever), but fails to stop when I use time.sleep
. Why does the timeout not work with the sleep timer and will this work as a way to prevent threads from hanging?
import signal
import time
def timeout(func, args=(), kwargs={}, timeout_duration=1, default=None):
class TimeoutError(Exception):
pass
def handler(signum, frame):
raise TimeoutError()
# set the timeout handler
signal.signal(signal.SIGALRM, handler)
signal.alarm(timeout_duration)
try:
result = func(*args, **kwargs)
except TimeoutError as exc:
result = default
finally:
signal.alarm(0)
return result
def loop_forever():
x = 0
while True:
print x
try:
x += 1
except:
continue
def loop_forever_sleep():
x = 0
while True:
print x
try:
x += 1
time.sleep(10)
except:
continue
if __name__ == '__main__':
a = timeout(loop_forever) #Terminates
b = timeout(loop_forever_sleep) #Does not terminate
Upvotes: 1
Views: 124
Reputation: 94871
The problem is that the SIGALRM
is being raised while you're inside of the time.sleep(10)
system call, which causes your handler
to be called in that context, too. However, you're swallowing all the exceptions that happen inside of your infinite loop, so the TimeoutError
never makes it back to the timeout
function, instead it gets ignored by the except: continue
code inside of loop_forever_sleep
. Just remove the try
/except
block from the while True
loop and it will work fine:
def loop_forever_sleep():
x = 0
while True:
print x
x += 1
time.sleep(10)
Upvotes: 1