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