Index: Objects/fileobject.c =================================================================== --- Objects/fileobject.c (revision 77910) +++ Objects/fileobject.c (working copy) @@ -1021,6 +1021,12 @@ #endif #endif +#if defined(EBADF) +#define ERRNO_EBADF(x) ((x) == EBADF) +#else +#define ERRNO_EBADF(x) 0 +#endif + static PyObject * file_read(PyFileObject *f, PyObject *args) { @@ -1056,7 +1062,7 @@ chunksize = Py_UniversalNewlineFread(BUF(v) + bytesread, buffersize - bytesread, f->f_fp, (PyObject *)f); FILE_END_ALLOW_THREADS(f) - if (chunksize == 0) { + if (ERRNO_EBADF(errno) || chunksize == 0) { if (!ferror(f->f_fp)) break; clearerr(f->f_fp); @@ -1115,7 +1121,7 @@ nnow = Py_UniversalNewlineFread(ptr+ndone, ntodo, f->f_fp, (PyObject *)f); FILE_END_ALLOW_THREADS(f) - if (nnow == 0) { + if (ERRNO_EBADF(errno) || nnow == 0) { if (!ferror(f->f_fp)) break; PyErr_SetFromErrno(PyExc_IOError); @@ -1222,7 +1228,14 @@ p = fgets(pvfree, (int)nfree, fp); FILE_END_ALLOW_THREADS(f) + /* XXX: Microsoft fgets() does not return NULL when reading + * from a write-only stream. */ if (p == NULL) { + if (ferror(fp)) { + PyErr_SetFromErrno(PyExc_IOError); + clearerr(fp); + return NULL; + } clearerr(fp); if (PyErr_CheckSignals()) return NULL; @@ -1298,6 +1311,12 @@ FILE_END_ALLOW_THREADS(f) if (p == NULL) { + if (ferror(fp)) { + PyErr_SetFromErrno(PyExc_IOError); + clearerr(fp); + Py_DECREF(v); + return NULL; + } clearerr(fp); if (PyErr_CheckSignals()) { Py_DECREF(v); @@ -1378,6 +1397,7 @@ for (;;) { FILE_BEGIN_ALLOW_THREADS(f) FLOCKFILE(fp); + errno = 0; if (univ_newline) { c = 'x'; /* Shut up gcc warning */ while ( buf != end && (c = GETC(fp)) != EOF ) { @@ -1414,10 +1434,9 @@ FILE_END_ALLOW_THREADS(f) f->f_newlinetypes = newlinetypes; f->f_skipnextlf = skipnextlf; - if (c == '\n') - break; - if (c == EOF) { - if (ferror(fp)) { + if (ERRNO_EBADF(errno) || c == EOF) { + /* XXX OpenSolaris sets errno (unreliably!) but not ferror. */ + if (ERRNO_EBADF(errno) || ferror(fp)) { PyErr_SetFromErrno(PyExc_IOError); clearerr(fp); Py_DECREF(v); @@ -1430,6 +1449,8 @@ } break; } + if (c == '\n') + break; /* Must be because buf == end */ if (n > 0) break; @@ -1601,17 +1622,17 @@ if ((list = PyList_New(0)) == NULL) return NULL; for (;;) { + errno = 0; if (shortread) nread = 0; else { FILE_BEGIN_ALLOW_THREADS(f) - errno = 0; nread = Py_UniversalNewlineFread(buffer+nfilled, buffersize-nfilled, f->f_fp, (PyObject *)f); FILE_END_ALLOW_THREADS(f) shortread = (nread < buffersize-nfilled); } - if (nread == 0) { + if (ERRNO_EBADF(errno) || nread == 0) { sizehint = 0; if (!ferror(f->f_fp)) break; @@ -2113,7 +2134,7 @@ chunksize = Py_UniversalNewlineFread( f->f_buf, bufsize, f->f_fp, (PyObject *)f); FILE_END_ALLOW_THREADS(f) - if (chunksize == 0) { + if (ERRNO_EBADF(errno) || chunksize == 0) { if (ferror(f->f_fp)) { PyErr_SetFromErrno(PyExc_IOError); clearerr(f->f_fp);