osdir.com


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Handle SIGINT in C and Python (Posting On Python-List Prohibited)


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