diff -r dc0811953034 Lib/_pyio.py --- a/Lib/_pyio.py Fri Mar 25 12:50:54 2016 +0100 +++ b/Lib/_pyio.py Fri Mar 25 13:56:34 2016 +0100 @@ -375,14 +375,19 @@ class IOBase(metaclass=abc.ABCMeta): def __del__(self): """Destructor. Calls close().""" - # The try/except block is in case this is called at program - # exit time, when it's possible that globals have already been - # deleted, and then the close() call might fail. Since - # there's nothing we can do about such failures and they annoy - # the end users, we suppress the traceback. + if self.closed: + return + + import warnings + warnings.warn('unclosed file %r' % (self,), ResourceWarning, + stacklevel=2, source=self) + try: self.close() except: + # Silencing I/O errors is bad, but printing spurious tracebacks is + # equally as bad, and potentially more frequent (because of + # shutdown issues). pass ### Inquiries ### @@ -1510,13 +1515,6 @@ class FileIO(RawIOBase): raise self._fd = fd - def __del__(self): - if self._fd >= 0 and self._closefd and not self.closed: - import warnings - warnings.warn('unclosed file %r' % (self,), ResourceWarning, - stacklevel=2, source=self) - self.close() - def __getstate__(self): raise TypeError("cannot serialize '%s' object", self.__class__.__name__) diff -r dc0811953034 Modules/_io/bufferedio.c --- a/Modules/_io/bufferedio.c Fri Mar 25 12:50:54 2016 +0100 +++ b/Modules/_io/bufferedio.c Fri Mar 25 13:56:34 2016 +0100 @@ -32,7 +32,6 @@ class io_ssize_t_converter(CConverter): /*[python end generated code: output=da39a3ee5e6b4b0d input=d0a811d3cbfd1b33]*/ _Py_IDENTIFIER(close); -_Py_IDENTIFIER(_dealloc_warn); _Py_IDENTIFIER(flush); _Py_IDENTIFIER(isatty); _Py_IDENTIFIER(mode); @@ -446,23 +445,6 @@ buffered_clear(buffered *self) return 0; } -/* 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). */ -static PyObject * -buffered_dealloc_warn(buffered *self, PyObject *source) -{ - if (self->ok && self->raw) { - PyObject *r; - r = _PyObject_CallMethodId(self->raw, &PyId__dealloc_warn, "O", source); - if (r) - Py_DECREF(r); - else - PyErr_Clear(); - } - Py_RETURN_NONE; -} - /* * _BufferedIOMixin methods * This is not a class, just a collection of methods that will be reused @@ -518,13 +500,6 @@ buffered_close(buffered *self, PyObject goto end; } - if (self->finalizing) { - PyObject *r = buffered_dealloc_warn(self, (PyObject *) self); - if (r) - Py_DECREF(r); - else - PyErr_Clear(); - } /* flush() will most probably re-take the lock, so drop it first */ LEAVE_BUFFERED(self) res = PyObject_CallMethodObjArgs((PyObject *)self, _PyIO_str_flush, NULL); @@ -2401,7 +2376,6 @@ static PyMethodDef bufferedreader_method {"writable", (PyCFunction)buffered_writable, METH_NOARGS}, {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS}, {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS}, - {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O}, {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS}, _IO__BUFFERED_READ_METHODDEF @@ -2493,7 +2467,6 @@ static PyMethodDef bufferedwriter_method {"writable", (PyCFunction)buffered_writable, METH_NOARGS}, {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS}, {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS}, - {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O}, {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS}, _IO_BUFFEREDWRITER_WRITE_METHODDEF @@ -2660,7 +2633,6 @@ static PyMethodDef bufferedrandom_method {"writable", (PyCFunction)buffered_writable, METH_NOARGS}, {"fileno", (PyCFunction)buffered_fileno, METH_NOARGS}, {"isatty", (PyCFunction)buffered_isatty, METH_NOARGS}, - {"_dealloc_warn", (PyCFunction)buffered_dealloc_warn, METH_O}, {"__getstate__", (PyCFunction)buffered_getstate, METH_NOARGS}, {"flush", (PyCFunction)buffered_flush, METH_NOARGS}, diff -r dc0811953034 Modules/_io/fileio.c --- a/Modules/_io/fileio.c Fri Mar 25 12:50:54 2016 +0100 +++ b/Modules/_io/fileio.c Fri Mar 25 13:56:34 2016 +0100 @@ -83,25 +83,6 @@ int return ((fileio *)self)->fd < 0; } -/* 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). */ -static PyObject * -fileio_dealloc_warn(fileio *self, PyObject *source) -{ - if (self->fd >= 0 && self->closefd) { - PyObject *exc, *val, *tb; - PyErr_Fetch(&exc, &val, &tb); - if (PyErr_ResourceWarning(source, 1, "unclosed file %R", source)) { - /* Spurious errors can appear at shutdown */ - if (PyErr_ExceptionMatches(PyExc_Warning)) - PyErr_WriteUnraisable((PyObject *) self); - } - PyErr_Restore(exc, val, tb); - } - Py_RETURN_NONE; -} - static PyObject * portable_lseek(int fd, PyObject *posobj, int whence); @@ -163,13 +144,6 @@ static PyObject * } if (res == NULL) PyErr_Fetch(&exc, &val, &tb); - if (self->finalizing) { - PyObject *r = fileio_dealloc_warn(self, (PyObject *) self); - if (r) - Py_DECREF(r); - else - PyErr_Clear(); - } rc = internal_close(self); if (res == NULL) _PyErr_ChainExceptions(exc, val, tb); @@ -1143,7 +1117,6 @@ static PyMethodDef fileio_methods[] = { _IO_FILEIO_WRITABLE_METHODDEF _IO_FILEIO_FILENO_METHODDEF _IO_FILEIO_ISATTY_METHODDEF - {"_dealloc_warn", (PyCFunction)fileio_dealloc_warn, METH_O, NULL}, {"__getstate__", (PyCFunction)fileio_getstate, METH_NOARGS, NULL}, {NULL, NULL} /* sentinel */ }; diff -r dc0811953034 Modules/_io/iobase.c --- a/Modules/_io/iobase.c Fri Mar 25 12:50:54 2016 +0100 +++ b/Modules/_io/iobase.c Fri Mar 25 13:56:34 2016 +0100 @@ -255,6 +255,12 @@ iobase_finalize(PyObject *self) PyErr_Clear(); } if (closed == 0) { + if (PyErr_ResourceWarning(self, 1, "unclosed file %R", self)) { + /* Spurious errors can appear at shutdown */ + if (PyErr_ExceptionMatches(PyExc_Warning)) + PyErr_WriteUnraisable((PyObject *) self); + } + /* Signal close() that it was called as part of the object finalization process. */ if (_PyObject_SetAttrId(self, &PyId__finalizing, Py_True)) diff -r dc0811953034 Modules/_io/textio.c --- a/Modules/_io/textio.c Fri Mar 25 12:50:54 2016 +0100 +++ b/Modules/_io/textio.c Fri Mar 25 13:56:34 2016 +0100 @@ -26,7 +26,6 @@ class io_ssize_t_converter(CConverter): /*[python end generated code: output=da39a3ee5e6b4b0d input=d0a811d3cbfd1b33]*/ _Py_IDENTIFIER(close); -_Py_IDENTIFIER(_dealloc_warn); _Py_IDENTIFIER(decode); _Py_IDENTIFIER(fileno); _Py_IDENTIFIER(flush); @@ -2650,13 +2649,6 @@ static PyObject * } else { PyObject *exc = NULL, *val, *tb; - if (self->finalizing) { - res = _PyObject_CallMethodId(self->buffer, &PyId__dealloc_warn, "O", self); - if (res) - Py_DECREF(res); - else - PyErr_Clear(); - } res = _PyObject_CallMethodId((PyObject *)self, &PyId_flush, NULL); if (res == NULL) PyErr_Fetch(&exc, &val, &tb);