summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2015-03-19 21:53:20 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2015-03-19 21:53:20 (GMT)
commit66aab0c4b5b6b328aebc115f96275e7dcd114f8b (patch)
treec607e0019befcb199fb8f916038d01a0b3b9a5f3 /Modules
parent9eb57c5fa50ed2f57d9320bb575371868316b5f2 (diff)
downloadcpython-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')
-rw-r--r--Modules/_io/fileio.c142
-rw-r--r--Modules/posixmodule.c46
2 files changed, 36 insertions, 152 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;
}
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index b8151c3..7aa8050 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -11207,37 +11207,27 @@ os_read_impl(PyModuleDef *module, int fd, Py_ssize_t length)
/*[clinic end generated code: output=1f3bc27260a24968 input=1df2eaa27c0bf1d3]*/
{
Py_ssize_t n;
- int async_err = 0;
PyObject *buffer;
if (length < 0) {
errno = EINVAL;
return posix_error();
}
- if (!_PyVerify_fd(fd))
- return posix_error();
#ifdef MS_WINDOWS
- #define READ_CAST (int)
+ /* On Windows, the count parameter of read() is an int */
if (length > INT_MAX)
length = INT_MAX;
-#else
- #define READ_CAST
#endif
buffer = PyBytes_FromStringAndSize((char *)NULL, length);
if (buffer == NULL)
return NULL;
- do {
- Py_BEGIN_ALLOW_THREADS
- n = read(fd, PyBytes_AS_STRING(buffer), READ_CAST length);
- Py_END_ALLOW_THREADS
- } while (n < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
-
- if (n < 0) {
+ n = _Py_read(fd, PyBytes_AS_STRING(buffer), length);
+ if (n == -1) {
Py_DECREF(buffer);
- return (!async_err) ? posix_error() : NULL;
+ return NULL;
}
if (n != length)
@@ -11541,33 +11531,7 @@ static Py_ssize_t
os_write_impl(PyModuleDef *module, int fd, Py_buffer *data)
/*[clinic end generated code: output=aeb96acfdd4d5112 input=3207e28963234f3c]*/
{
- Py_ssize_t size;
- int async_err = 0;
- Py_ssize_t len = data->len;
-
- if (!_PyVerify_fd(fd)) {
- posix_error();
- return -1;
- }
-
- do {
- Py_BEGIN_ALLOW_THREADS
-#ifdef MS_WINDOWS
- if (len > INT_MAX)
- len = INT_MAX;
- size = write(fd, data->buf, (int)len);
-#else
- size = write(fd, data->buf, len);
-#endif
- Py_END_ALLOW_THREADS
- } while (size < 0 && errno == EINTR && !(async_err = PyErr_CheckSignals()));
-
- if (size < 0) {
- if (!async_err)
- posix_error();
- return -1;
- }
- return size;
+ return _Py_write(fd, data->buf, data->len);
}
#ifdef HAVE_SENDFILE