Stoping a python task from rust code #6317
|
Hi! I am searching for a way to cancel a python task from rust code. To give you more context, I have a piece of rust code which execute a user defined python script. From this post, the only solution seems to be PyThreadState_SetAsyncExc, but the answer has been given few years ago so I want to confirme nothing else can be used. Thanks! |
Replies: 1 comment 1 reply
|
Confirmed, in-process there's still nothing besides PyThreadState_SetAsyncExc (pyo3 exposes it as pyo3::ffi::PyThreadState_SetAsyncExc). CPython has no API to force-kill a thread, so that part hasn't changed. Two gotchas before you lean on it. It injects a normal, catchable exception at Python bytecode boundaries, so (a) a script stuck in a blocking C call (time.sleep, blocking IO, a C extension) isn't interrupted until that call returns, and (b) even a pure-Python loop survives if it's wrapped in a broad For a script that might run forever, the only reliable timeout is running them in a separate process and SIGKILL-ing it. That path also covers the blocking-C case injection can't reach. |
Confirmed, in-process there's still nothing besides PyThreadState_SetAsyncExc (pyo3 exposes it as pyo3::ffi::PyThreadState_SetAsyncExc). CPython has no API to force-kill a thread, so that part hasn't changed.
Two gotchas before you lean on it. It injects a normal, catchable exception at Python bytecode boundaries, so (a) a script stuck in a blocking C call (time.sleep, blocking IO, a C extension) isn't interrupted until that call returns, and (b) even a pure-Python loop survives if it's wrapped in a broad
except:. On 3.9 an unguarded busy loop dies right after injection, but a time.sleep(30) thread and an except-guarded loop both stay alive even after SetAsyncExc returns 1. It also keys o…