diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2015-03-31 09:48:34 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2015-03-31 09:48:34 (GMT) |
commit | 4448c08451e947ccf197742d22fa49adba71e363 (patch) | |
tree | f1183e1f289ad178ec22e274644b86a6c3a0cf55 /Modules | |
parent | b6faf0dfa7e5d9f5b9f09bc1d1113069f1c962ab (diff) | |
download | cpython-4448c08451e947ccf197742d22fa49adba71e363.zip cpython-4448c08451e947ccf197742d22fa49adba71e363.tar.gz cpython-4448c08451e947ccf197742d22fa49adba71e363.tar.bz2 |
Issue #23485: select.kqueue.control() is now retried when interrupted by a signal
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/selectmodule.c | 45 |
1 files changed, 34 insertions, 11 deletions
diff --git a/Modules/selectmodule.c b/Modules/selectmodule.c index 96be5ba..452525d 100644 --- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -2083,8 +2083,9 @@ kqueue_queue_control(kqueue_queue_Object *self, PyObject *args) PyObject *result = NULL; struct kevent *evl = NULL; struct kevent *chl = NULL; - struct timespec timeout; + struct timespec timeoutspec; struct timespec *ptimeoutspec; + _PyTime_t timeout, deadline = 0; if (self->kqfd < 0) return kqueue_queue_err_closed(); @@ -2103,9 +2104,7 @@ kqueue_queue_control(kqueue_queue_Object *self, PyObject *args) ptimeoutspec = NULL; } else { - _PyTime_t ts; - - if (_PyTime_FromSecondsObject(&ts, + if (_PyTime_FromSecondsObject(&timeout, otimeout, _PyTime_ROUND_CEILING) < 0) { PyErr_Format(PyExc_TypeError, "timeout argument must be an number " @@ -2114,15 +2113,15 @@ kqueue_queue_control(kqueue_queue_Object *self, PyObject *args) return NULL; } - if (_PyTime_AsTimespec(ts, &timeout) == -1) + if (_PyTime_AsTimespec(timeout, &timeoutspec) == -1) return NULL; - if (timeout.tv_sec < 0) { + if (timeoutspec.tv_sec < 0) { PyErr_SetString(PyExc_ValueError, "timeout must be positive or None"); return NULL; } - ptimeoutspec = &timeout; + ptimeoutspec = &timeoutspec; } if (ch != NULL && ch != Py_None) { @@ -2167,10 +2166,34 @@ kqueue_queue_control(kqueue_queue_Object *self, PyObject *args) } } - Py_BEGIN_ALLOW_THREADS - gotevents = kevent(self->kqfd, chl, nchanges, - evl, nevents, ptimeoutspec); - Py_END_ALLOW_THREADS + if (ptimeoutspec) + deadline = _PyTime_GetMonotonicClock() + timeout; + + do { + Py_BEGIN_ALLOW_THREADS + errno = 0; + gotevents = kevent(self->kqfd, chl, nchanges, + evl, nevents, ptimeoutspec); + Py_END_ALLOW_THREADS + + if (errno != EINTR) + break; + + /* kevent() was interrupted by a signal */ + if (PyErr_CheckSignals()) + goto error; + + if (ptimeoutspec) { + timeout = deadline - _PyTime_GetMonotonicClock(); + if (timeout < 0) { + gotevents = 0; + break; + } + if (_PyTime_AsTimespec(timeout, &timeoutspec) == -1) + goto error; + /* retry kevent() with the recomputed timeout */ + } + } while (1); if (gotevents == -1) { PyErr_SetFromErrno(PyExc_OSError); |