diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2011-02-25 21:35:47 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2011-02-25 21:35:47 (GMT) |
commit | 6439c00a6dc1a079f7af0d8a44852fa75ece52a6 (patch) | |
tree | cb0bd75db802878c9f6ba0524d84938bc2062113 /Modules/_io | |
parent | 5217d3f9ca3ee5357f9dd9c47cfba04a00596c4a (diff) | |
download | cpython-6439c00a6dc1a079f7af0d8a44852fa75ece52a6.zip cpython-6439c00a6dc1a079f7af0d8a44852fa75ece52a6.tar.gz cpython-6439c00a6dc1a079f7af0d8a44852fa75ece52a6.tar.bz2 |
Merged revisions 88610 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/branches/py3k
........
r88610 | antoine.pitrou | 2011-02-25 22:24:11 +0100 (ven., 25 févr. 2011) | 4 lines
Issue #10956: Buffered I/O classes retry reading or writing after a signal
has arrived and the handler returned successfully.
........
Diffstat (limited to 'Modules/_io')
-rw-r--r-- | Modules/_io/bufferedio.c | 51 |
1 files changed, 49 insertions, 2 deletions
diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 18cf1ca..5816a93 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -683,6 +683,39 @@ _buffered_init(buffered *self) return 0; } +/* Return 1 if an EnvironmentError with errno == EINTR is set (and then + clears the error indicator), 0 otherwise. + Should only be called when PyErr_Occurred() is true. +*/ +static int +_trap_eintr(void) +{ + static PyObject *eintr_int = NULL; + PyObject *typ, *val, *tb; + PyEnvironmentErrorObject *env_err; + + if (eintr_int == NULL) { + eintr_int = PyLong_FromLong(EINTR); + assert(eintr_int != NULL); + } + if (!PyErr_ExceptionMatches(PyExc_EnvironmentError)) + return 0; + PyErr_Fetch(&typ, &val, &tb); + PyErr_NormalizeException(&typ, &val, &tb); + env_err = (PyEnvironmentErrorObject *) val; + assert(env_err != NULL); + if (env_err->myerrno != NULL && + PyObject_RichCompareBool(env_err->myerrno, eintr_int, Py_EQ) > 0) { + Py_DECREF(typ); + Py_DECREF(val); + Py_XDECREF(tb); + return 1; + } + /* This silences any error set by PyObject_RichCompareBool() */ + PyErr_Restore(typ, val, tb); + return 0; +} + /* * Shared methods and wrappers */ @@ -1243,7 +1276,14 @@ _bufferedreader_raw_read(buffered *self, char *start, Py_ssize_t len) memobj = PyMemoryView_FromBuffer(&buf); if (memobj == NULL) return -1; - res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL); + /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR + occurs so we needn't do it ourselves. + We then retry reading, ignoring the signal if no handler has + raised (see issue #10956). + */ + do { + res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_readinto, memobj, NULL); + } while (res == NULL && _trap_eintr()); Py_DECREF(memobj); if (res == NULL) return -1; @@ -1650,7 +1690,14 @@ _bufferedwriter_raw_write(buffered *self, char *start, Py_ssize_t len) memobj = PyMemoryView_FromBuffer(&buf); if (memobj == NULL) return -1; - res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL); + /* NOTE: PyErr_SetFromErrno() calls PyErr_CheckSignals() when EINTR + occurs so we needn't do it ourselves. + We then retry writing, ignoring the signal if no handler has + raised (see issue #10956). + */ + do { + res = PyObject_CallMethodObjArgs(self->raw, _PyIO_str_write, memobj, NULL); + } while (res == NULL && _trap_eintr()); Py_DECREF(memobj); if (res == NULL) return -1; |