Index: Modules/_fileio.c =================================================================== --- Modules/_fileio.c (revision 68340) +++ Modules/_fileio.c (working copy) @@ -41,34 +41,41 @@ #define PyFileIO_Check(op) (PyObject_TypeCheck((op), &PyFileIO_Type)) -/* Returns 0 on success, errno (which is < 0) on failure. */ +/* close/detach from the stream +This does nothing when not attached to a stream. When the stream should not +be closed by us, just detach from it. Returns zero on failure, in which case +an exception was already set. */ static int internal_close(PyFileIOObject *self) { - int save_errno = 0; - if (self->fd >= 0) { - int fd = self->fd; - self->fd = -1; - Py_BEGIN_ALLOW_THREADS - if (close(fd) < 0) - save_errno = errno; - Py_END_ALLOW_THREADS - } - return save_errno; + int saved_errno = 0; + int fd = self->fd; + self->fd = -1; + + /* if there is nothing to close or we are not supposed to close + the stream, we are done here. */ + if ((fd < 0) || (self->closefd == 0)) + return 1; + + /* Closing will flush buffers and that might block, so allow other + threads to run in the meantime. */ + Py_BEGIN_ALLOW_THREADS + if(close(fd)==-1) + saved_errno = errno; + Py_END_ALLOW_THREADS + + if (saved_errno == 0 ) + return 1; + + PyErr_SetString(PyExc_IOError, strerror(saved_errno)); + return 0; } static PyObject * fileio_close(PyFileIOObject *self) { - if (!self->closefd) { - self->fd = -1; - Py_RETURN_NONE; - } - errno = internal_close(self); - if (errno < 0) { - PyErr_SetFromErrno(PyExc_IOError); + if(!internal_close(self)) return NULL; - } Py_RETURN_NONE; } @@ -107,6 +114,7 @@ if (fstat(self->fd, &buf) == 0 && S_ISDIR(buf.st_mode)) { char *msg = strerror(EISDIR); PyObject *exc; + /* Ignore errors here? */ internal_close(self); exc = PyObject_CallFunction(PyExc_IOError, "(iss)", @@ -138,11 +146,9 @@ int closefd = 1; assert(PyFileIO_Check(oself)); - if (self->fd >= 0) { - /* Have to close the existing file first. */ - if (internal_close(self) < 0) - return -1; - } + /* Have to close the existing file first. */ + if (!internal_close(self)) + return -1; if (PyArg_ParseTupleAndKeywords(args, kwds, "i|si:fileio", kwlist, &fd, &mode, &closefd)) { @@ -292,12 +298,9 @@ if (self->weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *) self); - if (self->fd >= 0 && self->closefd) { - errno = internal_close(self); - if (errno < 0) { - PySys_WriteStderr("close failed: [Errno %d] %s\n", - errno, strerror(errno)); - } + if(!internal_close(self)) { + PyErr_Clear(); + PySys_WriteStderr("close failed\n"); } Py_TYPE(self)->tp_free((PyObject *)self);