diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2015-03-19 21:53:20 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2015-03-19 21:53:20 (GMT) |
commit | 66aab0c4b5b6b328aebc115f96275e7dcd114f8b (patch) | |
tree | c607e0019befcb199fb8f916038d01a0b3b9a5f3 /Modules/_io/fileio.c | |
parent | 9eb57c5fa50ed2f57d9320bb575371868316b5f2 (diff) | |
download | cpython-66aab0c4b5b6b328aebc115f96275e7dcd114f8b.zip cpython-66aab0c4b5b6b328aebc115f96275e7dcd114f8b.tar.gz cpython-66aab0c4b5b6b328aebc115f96275e7dcd114f8b.tar.bz2 |
Issue #23708: Add _Py_read() and _Py_write() functions to factorize code handle
EINTR error and special cases for Windows.
These functions now truncate the length to PY_SSIZE_T_MAX to have a portable
and reliable behaviour. For example, read() result is undefined if counter is
greater than PY_SSIZE_T_MAX on Linux.
Diffstat (limited to 'Modules/_io/fileio.c')
-rw-r--r-- | Modules/_io/fileio.c | 142 |
1 files changed, 31 insertions, 111 deletions
diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index 0f226ea..6152cde 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -570,8 +570,8 @@ static PyObject * fileio_readinto(fileio *self, PyObject *args) { Py_buffer pbuf; - Py_ssize_t n, len; - int err, async_err = 0; + Py_ssize_t n; + int err; if (self->fd < 0) return err_closed(); @@ -581,36 +581,16 @@ fileio_readinto(fileio *self, PyObject *args) if (!PyArg_ParseTuple(args, "w*", &pbuf)) return NULL; - if (_PyVerify_fd(self->fd)) { - len = pbuf.len; -#ifdef MS_WINDOWS - if (len > INT_MAX) - len = INT_MAX; -#endif - - do { - Py_BEGIN_ALLOW_THREADS - errno = 0; -#ifdef MS_WINDOWS - n = read(self->fd, pbuf.buf, (int)len); -#else - n = read(self->fd, pbuf.buf, len); -#endif - Py_END_ALLOW_THREADS - } while (n < 0 && errno == EINTR && - !(async_err = PyErr_CheckSignals())); - - if (async_err) - return NULL; - } else - n = -1; + n = _Py_read(self->fd, pbuf.buf, pbuf.len); + /* copy errno because PyBuffer_Release() can indirectly modify it */ err = errno; PyBuffer_Release(&pbuf); - if (n < 0) { - if (err == EAGAIN) + + if (n == -1) { + if (err == EAGAIN) { + PyErr_Clear(); Py_RETURN_NONE; - errno = err; - PyErr_SetFromErrno(PyExc_IOError); + } return NULL; } @@ -645,9 +625,8 @@ fileio_readall(fileio *self) Py_off_t pos, end; PyObject *result; Py_ssize_t bytes_read = 0; - Py_ssize_t len, n; + Py_ssize_t n; size_t bufsize; - int async_err = 0; if (self->fd < 0) return err_closed(); @@ -695,36 +674,21 @@ fileio_readall(fileio *self) } } - len = bufsize - bytes_read; -#ifdef MS_WINDOWS - if (len > INT_MAX) - len = INT_MAX; -#endif - do { - Py_BEGIN_ALLOW_THREADS - errno = 0; -#ifdef MS_WINDOWS - n = read(self->fd, PyBytes_AS_STRING(result) + bytes_read, (int)len); -#else - n = read(self->fd, PyBytes_AS_STRING(result) + bytes_read, len); -#endif - Py_END_ALLOW_THREADS - } while (n < 0 && errno == EINTR && - !(async_err = PyErr_CheckSignals())); + n = _Py_read(self->fd, + PyBytes_AS_STRING(result) + bytes_read, + bufsize - bytes_read); - if (async_err) - return NULL; if (n == 0) break; - if (n < 0) { + if (n == -1) { if (errno == EAGAIN) { + PyErr_Clear(); if (bytes_read > 0) break; Py_DECREF(result); Py_RETURN_NONE; } Py_DECREF(result); - PyErr_SetFromErrno(PyExc_IOError); return NULL; } bytes_read += n; @@ -756,7 +720,6 @@ fileio_read(fileio *self, PyObject *args) char *ptr; Py_ssize_t n; Py_ssize_t size = -1; - int async_err = 0; PyObject *bytes; if (self->fd < 0) @@ -767,44 +730,29 @@ fileio_read(fileio *self, PyObject *args) if (!PyArg_ParseTuple(args, "|O&", &_PyIO_ConvertSsize_t, &size)) return NULL; - if (size < 0) { + if (size < 0) return fileio_readall(self); - } #ifdef MS_WINDOWS + /* On Windows, the count parameter of read() is an int */ if (size > INT_MAX) size = INT_MAX; #endif + bytes = PyBytes_FromStringAndSize(NULL, size); if (bytes == NULL) return NULL; ptr = PyBytes_AS_STRING(bytes); - if (_PyVerify_fd(self->fd)) { - do { - Py_BEGIN_ALLOW_THREADS - errno = 0; -#ifdef MS_WINDOWS - n = read(self->fd, ptr, (int)size); -#else - n = read(self->fd, ptr, size); -#endif - Py_END_ALLOW_THREADS - } while (n < 0 && errno == EINTR && - !(async_err = PyErr_CheckSignals())); - - if (async_err) - return NULL; - } else - n = -1; - - if (n < 0) { + n = _Py_read(self->fd, ptr, size); + if (n == -1) { + /* copy errno because Py_DECREF() can indirectly modify it */ int err = errno; Py_DECREF(bytes); - if (err == EAGAIN) + if (err == EAGAIN) { + PyErr_Clear(); Py_RETURN_NONE; - errno = err; - PyErr_SetFromErrno(PyExc_IOError); + } return NULL; } @@ -822,8 +770,8 @@ static PyObject * fileio_write(fileio *self, PyObject *args) { Py_buffer pbuf; - Py_ssize_t n, len; - int err, async_err = 0; + Py_ssize_t n; + int err; if (self->fd < 0) return err_closed(); @@ -833,44 +781,16 @@ fileio_write(fileio *self, PyObject *args) if (!PyArg_ParseTuple(args, "y*", &pbuf)) return NULL; - if (_PyVerify_fd(self->fd)) { - len = pbuf.len; -#ifdef MS_WINDOWS - if (len > 32767 && isatty(self->fd)) { - /* Issue #11395: the Windows console returns an error (12: not - enough space error) on writing into stdout if stdout mode is - binary and the length is greater than 66,000 bytes (or less, - depending on heap usage). */ - len = 32767; - } else if (len > INT_MAX) - len = INT_MAX; -#endif - - do { - Py_BEGIN_ALLOW_THREADS - errno = 0; -#ifdef MS_WINDOWS - n = write(self->fd, pbuf.buf, (int)len); -#else - n = write(self->fd, pbuf.buf, len); -#endif - Py_END_ALLOW_THREADS - } while (n < 0 && errno == EINTR && - !(async_err = PyErr_CheckSignals())); - - if (async_err) - return NULL; - } else - n = -1; + n = _Py_write(self->fd, pbuf.buf, pbuf.len); + /* copy errno because PyBuffer_Release() can indirectly modify it */ err = errno; - PyBuffer_Release(&pbuf); if (n < 0) { - if (err == EAGAIN) + if (err == EAGAIN) { + PyErr_Clear(); Py_RETURN_NONE; - errno = err; - PyErr_SetFromErrno(PyExc_IOError); + } return NULL; } |