From 2d601ef157ffcd0d15749fbfb2d5e7fc684144fb Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Tue, 26 Aug 2014 02:27:51 +0100 Subject: [PATCH] Fixed memory leak with large objects Deallocating closed large objects failed to decrement the connection refcount. The fact the lobject is closed doesn't matter for refcount. Issue detected by the always useful scripts/refcounter.py With an extra bit of unrequested whitespace love. --- NEWS | 1 + psycopg/lobject_type.c | 13 ++++++------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/NEWS b/NEWS index 8e739a0e..66d9aac8 100644 --- a/NEWS +++ b/NEWS @@ -26,6 +26,7 @@ What's new in psycopg 2.5.4 PostgreSQL but not documented. - Make sure the internal `_psycopg.so` module can be imported stand-alone (to allow modules juggling such as the one described in :ticket:`#201`). +- Fixed memory leak with large objects (regression introduced in 2.5.3). What's new in psycopg 2.5.3 diff --git a/psycopg/lobject_type.c b/psycopg/lobject_type.c index e62ddc27..ef442f90 100644 --- a/psycopg/lobject_type.c +++ b/psycopg/lobject_type.c @@ -50,7 +50,7 @@ psyco_lobj_close(lobjectObject *self, PyObject *args) opened large objects */ if (!lobject_is_closed(self) && !self->conn->autocommit - && self->conn->mark == self->mark) + && self->conn->mark == self->mark) { Dprintf("psyco_lobj_close: closing lobject at %p", self); if (lobject_close(self) < 0) @@ -169,14 +169,14 @@ psyco_lobj_seek(lobjectObject *self, PyObject *args) int pos=0; if (!PyArg_ParseTuple(args, "i|i", &offset, &whence)) - return NULL; + return NULL; EXC_IF_LOBJ_CLOSED(self); EXC_IF_LOBJ_LEVEL0(self); EXC_IF_LOBJ_UNMARKED(self); if ((pos = lobject_seek(self, offset, whence)) < 0) - return NULL; + return NULL; return PyInt_FromLong((long)pos); } @@ -196,7 +196,7 @@ psyco_lobj_tell(lobjectObject *self, PyObject *args) EXC_IF_LOBJ_UNMARKED(self); if ((pos = lobject_tell(self)) < 0) - return NULL; + return NULL; return PyInt_FromLong((long)pos); } @@ -329,11 +329,10 @@ lobject_setup(lobjectObject *self, connectionObject *conn, return -1; } + Py_INCREF((PyObject*)conn); self->conn = conn; self->mark = conn->mark; - Py_INCREF((PyObject*)self->conn); - self->fd = -1; self->oid = InvalidOid; @@ -354,8 +353,8 @@ lobject_dealloc(PyObject* obj) if (self->conn && self->fd != -1) { if (lobject_close(self) < 0) PyErr_Print(); - Py_XDECREF((PyObject*)self->conn); } + Py_CLEAR(self->conn); PyMem_Free(self->smode); Dprintf("lobject_dealloc: deleted lobject object at %p, refcnt = "