diff options
author | Gustavo Niemeyer <gustavo@niemeyer.net> | 2002-12-16 18:12:53 (GMT) |
---|---|---|
committer | Gustavo Niemeyer <gustavo@niemeyer.net> | 2002-12-16 18:12:53 (GMT) |
commit | 786ddb29c9170a585ca1010bd392fb5a5ff4078c (patch) | |
tree | f13b95625431e6be163ae9f0a03118b3f9d13a0d /Objects/fileobject.c | |
parent | 17c5a33582be263e3d3484f1c16f17dadeea5b6f (diff) | |
download | cpython-786ddb29c9170a585ca1010bd392fb5a5ff4078c.zip cpython-786ddb29c9170a585ca1010bd392fb5a5ff4078c.tar.gz cpython-786ddb29c9170a585ca1010bd392fb5a5ff4078c.tar.bz2 |
Fixed bug
[#521782] unreliable file.read() error handling
* Objects/fileobject.c
(file_read): Clear errors before leaving the loop in all situations,
and also check if some data was read before exiting the loop with an
EWOULDBLOCK exception.
* Doc/lib/libstdtypes.tex
* Objects/fileobject.c
Document that sometimes a read() operation can return less data than
what the user asked, if running in non-blocking mode.
* Misc/NEWS
Document the fix.
Diffstat (limited to 'Objects/fileobject.c')
-rw-r--r-- | Objects/fileobject.c | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/Objects/fileobject.c b/Objects/fileobject.c index 86620ff..612cefd 100644 --- a/Objects/fileobject.c +++ b/Objects/fileobject.c @@ -741,6 +741,20 @@ new_buffersize(PyFileObject *f, size_t currentsize) return currentsize + SMALLCHUNK; } +#if defined(EWOULDBLOCK) && defined(EAGAIN) && EWOULDBLOCK != EAGAIN +#define BLOCKED_ERRNO(x) ((x) == EWOULDBLOCK || (x) == EAGAIN) +#else +#ifdef EWOULDBLOCK +#define BLOCKED_ERRNO(x) ((x) == EWOULDBLOCK) +#else +#ifdef EAGAIN +#define BLOCKED_ERRNO(x) ((x) == EAGAIN) +#else +#define BLOCKED_ERRNO(x) 0 +#endif +#endif +#endif + static PyObject * file_read(PyFileObject *f, PyObject *args) { @@ -774,18 +788,29 @@ file_read(PyFileObject *f, PyObject *args) if (chunksize == 0) { if (!ferror(f->f_fp)) break; - PyErr_SetFromErrno(PyExc_IOError); clearerr(f->f_fp); + /* When in non-blocking mode, data shouldn't + * be discarded if a blocking signal was + * received. That will also happen if + * chunksize != 0, but bytesread < buffersize. */ + if (bytesread > 0 && BLOCKED_ERRNO(errno)) + break; + PyErr_SetFromErrno(PyExc_IOError); Py_DECREF(v); return NULL; } bytesread += chunksize; - if (bytesread < buffersize) + if (bytesread < buffersize) { + clearerr(f->f_fp); break; + } if (bytesrequested < 0) { buffersize = new_buffersize(f, buffersize); if (_PyString_Resize(&v, buffersize) < 0) return NULL; + } else { + assert(bytesread == bytesrequested); + break; } } if (bytesread != buffersize) @@ -1518,7 +1543,9 @@ PyDoc_STRVAR(readline_doc, PyDoc_STRVAR(read_doc, "read([size]) -> read at most size bytes, returned as a string.\n" "\n" -"If the size argument is negative or omitted, read until EOF is reached."); +"If the size argument is negative or omitted, read until EOF is reached.\n" +"Notice that when in non-blocking mode, less data than what was requested\n" +"may be returned, even if no size parameter was given."); PyDoc_STRVAR(write_doc, "write(str) -> None. Write string str to file.\n" |