diff options
| author | Antoine Pitrou <solipsis@pitrou.net> | 2010-10-29 10:38:18 +0000 |
|---|---|---|
| committer | Antoine Pitrou <solipsis@pitrou.net> | 2010-10-29 10:38:18 +0000 |
| commit | e033e06db077d5abcb4bc3729d03f8a4a09b2486 (patch) | |
| tree | 04445ffa669d4d0df240d680249c7d7a7f661bd4 /Modules/_io/fileio.c | |
| parent | 9cbdd75ec5deda8f55edd7caab42dff65d009da2 (diff) | |
| download | cpython-git-e033e06db077d5abcb4bc3729d03f8a4a09b2486.tar.gz | |
Issue #10093: ResourceWarnings are now issued when files and sockets are
deallocated without explicit closing. These warnings are silenced by
default, except in pydebug mode.
Diffstat (limited to 'Modules/_io/fileio.c')
| -rw-r--r-- | Modules/_io/fileio.c | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/Modules/_io/fileio.c b/Modules/_io/fileio.c index 74009e3657..16b98d6f67 100644 --- a/Modules/_io/fileio.c +++ b/Modules/_io/fileio.c @@ -2,6 +2,7 @@ #define PY_SSIZE_T_CLEAN #include "Python.h" +#include "structmember.h" #ifdef HAVE_SYS_TYPES_H #include <sys/types.h> #endif @@ -55,6 +56,7 @@ typedef struct { unsigned int writable : 1; signed int seekable : 2; /* -1 means unknown */ unsigned int closefd : 1; + unsigned int deallocating: 1; PyObject *weakreflist; PyObject *dict; } fileio; @@ -69,6 +71,26 @@ _PyFileIO_closed(PyObject *self) 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_WarnFormat(PyExc_ResourceWarning, 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); @@ -110,6 +132,13 @@ fileio_close(fileio *self) self->fd = -1; Py_RETURN_NONE; } + if (self->deallocating) { + PyObject *r = fileio_dealloc_warn(self, (PyObject *) self); + if (r) + Py_DECREF(r); + else + PyErr_Clear(); + } errno = internal_close(self); if (errno < 0) return NULL; @@ -399,6 +428,7 @@ fileio_clear(fileio *self) static void fileio_dealloc(fileio *self) { + self->deallocating = 1; if (_PyIOBase_finalize((PyObject *) self) < 0) return; _PyObject_GC_UNTRACK(self); @@ -1008,6 +1038,7 @@ static PyMethodDef fileio_methods[] = { {"writable", (PyCFunction)fileio_writable, METH_NOARGS, writable_doc}, {"fileno", (PyCFunction)fileio_fileno, METH_NOARGS, fileno_doc}, {"isatty", (PyCFunction)fileio_isatty, METH_NOARGS, isatty_doc}, + {"_dealloc_warn", (PyCFunction)fileio_dealloc_warn, METH_O, NULL}, {NULL, NULL} /* sentinel */ }; |
