diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index f30d54a5e11b0a..a1ba4d739dd4ab 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -518,6 +518,8 @@ buffered_closed_get(buffered *self, void *context) return PyObject_GetAttr(self->raw, &_Py_ID(closed)); } +void _PyFileIO_set_defer_close(PyObject *self, bool defer_close); + /*[clinic input] _io._Buffered.close [clinic start generated code]*/ @@ -563,6 +565,10 @@ _io__Buffered_close_impl(buffered *self) Py_DECREF(res); } + if (self->fast_closed_checks) { + _PyFileIO_set_defer_close(self->raw, false); + } + res = PyObject_CallMethodNoArgs(self->raw, &_Py_ID(close)); if (self->buffer) { @@ -1891,6 +1897,9 @@ _io_BufferedWriter___init___impl(buffered *self, PyObject *raw, Py_IS_TYPE(self, state->PyBufferedWriter_Type) && Py_IS_TYPE(raw, state->PyFileIO_Type) ); + if (self->fast_closed_checks) { + _PyFileIO_set_defer_close(self->raw, true); + } self->ok = 1; return 0; diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index 30944fc56bf70e..9cfa39dadac1ee 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -70,6 +70,8 @@ typedef struct { unsigned int blksize; PyObject *weakreflist; PyObject *dict; + /* if true, we are wrapped by buffer, don't close until buffer is closed */ + bool defer_close; } fileio; #define PyFileIO_Check(state, op) (PyObject_TypeCheck((op), state->PyFileIO_Type)) @@ -83,6 +85,13 @@ _PyFileIO_closed(PyObject *self) return ((fileio *)self)->fd < 0; } +void +_PyFileIO_set_defer_close(PyObject *self, bool defer_close) +{ + ((fileio *)self)->defer_close = defer_close; +} + + /* Because this can call arbitrary code, it shouldn't be called when the refcount is 0 (that is, not directly from tp_dealloc unless the refcount has been temporarily re-incremented). */ @@ -105,6 +114,9 @@ fileio_dealloc_warn(fileio *self, PyObject *source) static int internal_close(fileio *self) { + if (self->defer_close) { + return 0; + } int err = 0; int save_errno = 0; if (self->fd >= 0) { @@ -194,6 +206,7 @@ fileio_new(PyTypeObject *type, PyObject *args, PyObject *kwds) self->blksize = 0; self->closefd = 1; self->weakreflist = NULL; + self->defer_close = false; } return (PyObject *) self;