Reputation: 243
I'm trying to create a timeout, where if a function doesn't finish execution in time, a default value is returned. What I have below seems like it would work, except that the KeyboardInterrupt
exception is raised in the main thread, whereas my callback function is in a separate thread.
Is there any way in Python of specifying which thread the exception is raised in?
def interrupt():
raise KeyboardInterrupt
def callback_function():
# Start 16 ms timer
timer = threading.Timer(0.016, interrupt)
timer.start()
try:
result = inconsistent_execution_time_function(data)
timer.cancel()
except KeyboardInterrupt:
print("Long execution time")
result = default
return result
Upvotes: 0
Views: 950
Reputation: 7459
As you surmised your solution doesn't work because threading.Timer()
is implemented using a separate thread (not the main thread) and thus can't propagate an exception to the original thread. Your approach won't work.
The usual solution is to employ a cooperative approach. Create a context object, possibly using thread local storage. That context object starts out with the boolean representing whether a timeout occurred set to false. Your interrupt()
function sets that var to true. Your inconsistent_execution_time_function()
then periodically checks whether the var is true.
But if you absolutely want to send a signal, possibly to interrupt a long running syscall, you should use signal.pthread_kill()
in your timer function. Obviously you will need to send the thread ID of your callback_function()
to that function by adding an appropriate parameter to its definition and add a args=(threading.ident)
parameter to the threading.Timer()
call.
Upvotes: 1