Message 150319 - Python tracker (original) (raw)
If SIGINT arrives while a function implemented in C is executing, then it prevents the function from raising an exception unless the function first calls PyErr_CheckSignals(). (If the function returns an object (instead of NULL) then KeyboardInterrupt is raised as expected.)
For example, the following function just spins for 5 seconds before raising RuntimeError:
static PyObject * testsigint_wait(PyObject *self, PyObject arg) { clock_t start = clock(); while (clock() - start < 5 * CLOCKS_PER_SEC) { / pass */ } //PyErr_CheckSignals(); PyErr_SetNone(PyExc_RuntimeError); return NULL; }
If I call this function and press Ctrl-C before it completes, then I get the following:
import testsigint a = testsigint.wait() ^C>>> print(a) Traceback (most recent call last): File "", line 1, in NameError: name 'a' is not defined
So the call failed, but no exception was raised, and the variable "a" was not set!
I would have expected RuntimeError (or KeyboardInterrupt) to be raised. If I uncomment the PyErr_CheckSignals() line then I get RuntimeError as expected:
import testsigint a = testsigint.wait() ^CTraceback (most recent call last): File "", line 1, in RuntimeError
Also, if I wrap the call in try...finally or try...except, I get a sensible "chained" traceback:
try: ... testsigint.wait() ... finally: ... print("done") ... ^CTraceback (most recent call last): File "", line 2, in RuntimeError
During handling of the above exception, another exception occurred:
Traceback (most recent call last): File "", line 2, in KeyboardInterrupt
(Tested under Linux and Windows with the default branch.)