Handle SIGINT in C and Python (Posting On Python-List Prohibited)
eryk sun
eryksun at gmail.com
Thu Feb 1 00:59:18 EST 2018
On Thu, Feb 1, 2018 at 4:57 AM, Victor Porton <porton at narod.ru> wrote:
> Lawrence D’Oliveiro wrote:
>
>> On Thursday, February 1, 2018 at 8:10:24 AM UTC+13, Victor Porton wrote:
>>> Lawrence D’Oliveiro wrote:
>>>
>>>> The usual behaviour for POSIX is that the call is aborted with EINTR
>>>> after you get the signal.
>>>
>>> That poll() is interrupted does not imply that Python will run its
>>> pythonic signal handler at the point of interruption. That is a problem.
>>
>> * Python calls poll()
>> * poll() aborted with EINTR
>> * Python runs your signal handler
>>
>> Versus native C code:
>>
>> * your code calls poll()
>> * poll() aborted with EINTR
>> * your signal handler is run
>>
>> Where is there a fundamental difference?
>
> I meant to call poll() from C code, not Python code. In this case when
> poll() is aborted with EINTR, the pythonic signal handler does not run.
An extension module should call PyErr_CheckSignals [1] when
interrupted by EINTR. For example, here's the loop used to call poll()
in the standard-library select module:
async_err = 0;
do {
Py_BEGIN_ALLOW_THREADS
errno = 0;
poll_result = poll(self->ufds, self->ufd_len, (int)ms);
Py_END_ALLOW_THREADS
if (errno != EINTR)
break;
/* poll() was interrupted by a signal */
if (PyErr_CheckSignals()) {
async_err = 1;
break;
}
if (timeout >= 0) {
timeout = deadline - _PyTime_GetMonotonicClock();
if (timeout < 0) {
poll_result = 0;
break;
}
ms = _PyTime_AsMilliseconds(timeout, _PyTime_ROUND_CEILING);
/* retry poll() with the recomputed timeout */
}
} while (1);
self->poll_running = 0;
if (poll_result < 0) {
if (!async_err)
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
[1]: https://docs.python.org/3/c-api/exceptions.html#c.PyErr_CheckSignals
More information about the Python-list
mailing list