cpython: f54bc2c52dfd (original) (raw)
Mercurial > cpython
changeset 95314:f54bc2c52dfd
Issue #23485: select.devpoll.poll() is now retried when interrupted by a signal [#23485]
Victor Stinner victor.stinner@gmail.com | |
---|---|
date | Tue, 31 Mar 2015 12:10:33 +0200 |
parents | b017ca5d28bc |
children | 76d297869859 |
files | Doc/library/select.rst Doc/whatsnew/3.5.rst Lib/selectors.py Lib/test/eintrdata/eintr_tester.py Modules/selectmodule.c |
diffstat | 5 files changed, 85 insertions(+), 49 deletions(-)[+] [-] Doc/library/select.rst 6 Doc/whatsnew/3.5.rst 4 Lib/selectors.py 7 Lib/test/eintrdata/eintr_tester.py 11 Modules/selectmodule.c 106 |
line wrap: on
line diff
--- a/Doc/library/select.rst
+++ b/Doc/library/select.rst
@@ -249,6 +249,12 @@ object.
returning. If timeout is omitted, -1, or :const:None
, the call will
block until there is an event for this poll object.
- .. versionchanged:: 3.5
The function is now retried with a recomputed timeout when interrupted by[](#l1.8)
a signal, except if the signal handler raises an exception (see[](#l1.9)
:pep:`475` for the rationale), instead of raising[](#l1.10)
:exc:`InterruptedError`.[](#l1.11)
--- a/Doc/whatsnew/3.5.rst
+++ b/Doc/whatsnew/3.5.rst
@@ -619,10 +619,10 @@ Changes in the Python API
instead of raising :exc:InterruptedError
if the signal handler does not
raise an exception:
--- a/Lib/selectors.py +++ b/Lib/selectors.py @@ -479,11 +479,10 @@ if hasattr(select, 'devpoll'): # devpoll() has a resolution of 1 millisecond, round away from # zero to wait at least timeout seconds. timeout = math.ceil(timeout * 1e3) +
fd_event_list = self._devpoll.poll(timeout)[](#l3.8)
try:[](#l3.11)
fd_event_list = self._devpoll.poll(timeout)[](#l3.12)
except InterruptedError:[](#l3.13)
return ready[](#l3.14) for fd, event in fd_event_list:[](#l3.15) events = 0[](#l3.16) if event & ~select.POLLIN:[](#l3.17)
--- a/Lib/test/eintrdata/eintr_tester.py +++ b/Lib/test/eintrdata/eintr_tester.py @@ -351,6 +351,17 @@ class SelectEINTRTest(EINTRBaseTest): self.stop_alarm() self.assertGreaterEqual(dt, self.sleep_time)
- @unittest.skipUnless(hasattr(select, 'devpoll'), 'need select.devpoll')
- def test_devpoll(self):
poller = select.devpoll()[](#l4.9)
self.addCleanup(poller.close)[](#l4.10)
t0 = time.monotonic()[](#l4.12)
poller.poll(self.sleep_time * 1e3)[](#l4.13)
dt = time.monotonic() - t0[](#l4.14)
self.stop_alarm()[](#l4.15)
self.assertGreaterEqual(dt, self.sleep_time)[](#l4.16)
+ def test_main(): support.run_unittest(
--- a/Modules/selectmodule.c +++ b/Modules/selectmodule.c @@ -876,40 +876,38 @@ static PyObject * devpoll_poll(devpollObject *self, PyObject *args) { struct dvpoll dvp;
if (self->fd_devpoll < 0) return devpoll_err_closed();
- if (!PyArg_ParseTuple(args, "|O:poll", &timeout_obj)) { return NULL; } /* Check values for timeout */
- else if (!PyNumber_Check(tout)) {
PyErr_SetString(PyExc_TypeError,[](#l5.27)
"timeout must be an integer or None");[](#l5.28)
return NULL;[](#l5.29)
tout = PyNumber_Long(tout);[](#l5.33)
if (!tout)[](#l5.34)
return NULL;[](#l5.35)
timeout = PyLong_AsLong(tout);[](#l5.36)
Py_DECREF(tout);[](#l5.37)
if (timeout == -1 && PyErr_Occurred())[](#l5.38)
if (_PyTime_FromMillisecondsObject(&timeout, timeout_obj,[](#l5.39)
_PyTime_ROUND_CEILING) < 0) {[](#l5.40)
if (PyErr_ExceptionMatches(PyExc_TypeError)) {[](#l5.41)
PyErr_SetString(PyExc_TypeError,[](#l5.42)
"timeout must be an integer or None");[](#l5.43)
}[](#l5.44) return NULL;[](#l5.45)
}[](#l5.47)
- if ((timeout < -1) || (timeout > INT_MAX)) {
PyErr_SetString(PyExc_OverflowError,[](#l5.50)
"timeout is out of range");[](#l5.51)
return NULL;[](#l5.52)
ms = _PyTime_AsMilliseconds(timeout, _PyTime_ROUND_CEILING);[](#l5.53)
if (ms < -1 || ms > INT_MAX) {[](#l5.54)
PyErr_SetString(PyExc_OverflowError, "timeout is too large");[](#l5.55)
return NULL;[](#l5.56)
} if (devpoll_flush(self)) @@ -917,12 +915,36 @@ devpoll_poll(devpollObject *self, PyObje dvp.dp_fds = self->fds; dvp.dp_nfds = self->max_n_fds;}[](#l5.57)
- do {
/* call devpoll() */[](#l5.72)
Py_BEGIN_ALLOW_THREADS[](#l5.73)
errno = 0;[](#l5.74)
poll_result = ioctl(self->fd_devpoll, DP_POLL, &dvp);[](#l5.75)
Py_END_ALLOW_THREADS[](#l5.76)
if (errno != EINTR)[](#l5.78)
break;[](#l5.79)
- /* call devpoll() */
- Py_BEGIN_ALLOW_THREADS
- poll_result = ioctl(self->fd_devpoll, DP_POLL, &dvp);
- Py_END_ALLOW_THREADS
/* devpoll() was interrupted by a signal */[](#l5.85)
if (PyErr_CheckSignals())[](#l5.86)
return NULL;[](#l5.87)
if (timeout >= 0) {[](#l5.89)
timeout = deadline - _PyTime_GetMonotonicClock();[](#l5.90)
if (timeout < 0) {[](#l5.91)
poll_result = 0;[](#l5.92)
break;[](#l5.93)
}[](#l5.94)
ms = _PyTime_AsMilliseconds(timeout, _PyTime_ROUND_CEILING);[](#l5.95)
dvp.dp_timeout = (int)ms;[](#l5.96)
/* retry devpoll() with the recomputed timeout */[](#l5.97)
}[](#l5.98)
- } while (1);
if (poll_result < 0) { PyErr_SetFromErrno(PyExc_IOError); @@ -930,28 +952,26 @@ devpoll_poll(devpollObject self, PyObje } / build the result list */ - result_list = PyList_New(poll_result); if (!result_list) return NULL;
- else {
for (i = 0; i < poll_result; i++) {[](#l5.112)
num1 = PyLong_FromLong(self->fds[i].fd);[](#l5.113)
num2 = PyLong_FromLong(self->fds[i].revents);[](#l5.114)
if ((num1 == NULL) || (num2 == NULL)) {[](#l5.115)
Py_XDECREF(num1);[](#l5.116)
Py_XDECREF(num2);[](#l5.117)
goto error;[](#l5.118)
}[](#l5.119)
value = PyTuple_Pack(2, num1, num2);[](#l5.120)
Py_DECREF(num1);[](#l5.121)
Py_DECREF(num2);[](#l5.122)
if (value == NULL)[](#l5.123)
goto error;[](#l5.124)
if ((PyList_SetItem(result_list, i, value)) == -1) {[](#l5.125)
Py_DECREF(value);[](#l5.126)
goto error;[](#l5.127)
}[](#l5.128)
- for (i = 0; i < poll_result; i++) {
num1 = PyLong_FromLong(self->fds[i].fd);[](#l5.131)
num2 = PyLong_FromLong(self->fds[i].revents);[](#l5.132)
if ((num1 == NULL) || (num2 == NULL)) {[](#l5.133)
Py_XDECREF(num1);[](#l5.134)
Py_XDECREF(num2);[](#l5.135)
goto error;[](#l5.136)
}[](#l5.137)
value = PyTuple_Pack(2, num1, num2);[](#l5.138)
Py_DECREF(num1);[](#l5.139)
Py_DECREF(num2);[](#l5.140)
if (value == NULL)[](#l5.141)
goto error;[](#l5.142)
if ((PyList_SetItem(result_list, i, value)) == -1) {[](#l5.143)
Py_DECREF(value);[](#l5.144)
}goto error;[](#l5.145) }[](#l5.146)