diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2010-10-29 10:38:18 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2010-10-29 10:38:18 (GMT) |
commit | e033e06db077d5abcb4bc3729d03f8a4a09b2486 (patch) | |
tree | 04445ffa669d4d0df240d680249c7d7a7f661bd4 /Modules/_io/bufferedio.c | |
parent | 9cbdd75ec5deda8f55edd7caab42dff65d009da2 (diff) | |
download | cpython-e033e06db077d5abcb4bc3729d03f8a4a09b2486.zip cpython-e033e06db077d5abcb4bc3729d03f8a4a09b2486.tar.gz cpython-e033e06db077d5abcb4bc3729d03f8a4a09b2486.tar.bz2 |
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/bufferedio.c')
-rw-r--r-- | Modules/_io/bufferedio.c | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index 615e644..3045169 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -197,6 +197,7 @@ typedef struct { int detached; int readable; int writable; + int deallocating; /* True if this is a vanilla Buffered object (rather than a user derived class) *and* the raw stream is a vanilla FileIO object. */ @@ -342,6 +343,7 @@ typedef struct { static void buffered_dealloc(buffered *self) { + self->deallocating = 1; if (self->ok && _PyIOBase_finalize((PyObject *) self) < 0) return; _PyObject_GC_UNTRACK(self); @@ -382,6 +384,23 @@ 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). */ +PyObject * +buffered_dealloc_warn(buffered *self, PyObject *source) +{ + if (self->ok && self->raw) { + PyObject *r; + r = PyObject_CallMethod(self->raw, "_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 @@ -435,6 +454,14 @@ buffered_close(buffered *self, PyObject *args) Py_INCREF(res); goto end; } + + if (self->deallocating) { + 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); @@ -1461,6 +1488,7 @@ static PyMethodDef bufferedreader_methods[] = { {"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}, {"read", (PyCFunction)buffered_read, METH_VARARGS}, {"peek", (PyCFunction)buffered_peek, METH_VARARGS}, @@ -1843,6 +1871,7 @@ static PyMethodDef bufferedwriter_methods[] = { {"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}, {"write", (PyCFunction)bufferedwriter_write, METH_VARARGS}, {"truncate", (PyCFunction)buffered_truncate, METH_VARARGS}, @@ -2227,6 +2256,7 @@ static PyMethodDef bufferedrandom_methods[] = { {"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}, {"flush", (PyCFunction)buffered_flush, METH_NOARGS}, @@ -2296,4 +2326,3 @@ PyTypeObject PyBufferedRandom_Type = { 0, /* tp_alloc */ PyType_GenericNew, /* tp_new */ }; - |