From 3b8abf3fc4d0ccccb36a226be03387d02e817cea Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Thu, 21 Mar 2013 11:51:29 +0000 Subject: [PATCH] Clean the C members of Error in tp_dealloc instead of tp_clear tp_clear should only be used to break the reference cycles. tp_clear was causing a segfault because it was called twice (by the gc and by _dealloc) so self->codec was freed twice. Amazingly the double free was only causing a segfault on Python 3.3 (released in late 2012) talking to Postgres 8.1 (released in 2005) in async mode... no other combination crashed. Thank you buildbot. --- psycopg/error_type.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/psycopg/error_type.c b/psycopg/error_type.c index fd0947bc..95ce071a 100644 --- a/psycopg/error_type.c +++ b/psycopg/error_type.c @@ -93,6 +93,7 @@ error_traverse(errorObject *self, visitproc visit, void *arg) Py_VISIT(self->pgerror); Py_VISIT(self->pgcode); Py_VISIT(self->cursor); + return ((PyTypeObject *)PyExc_StandardError)->tp_traverse( (PyObject *)self, visit, arg); } @@ -104,16 +105,17 @@ error_clear(errorObject *self) Py_CLEAR(self->pgcode); Py_CLEAR(self->cursor); - PyMem_Free(self->codec); - CLEARPGRES(self->pgres); - return ((PyTypeObject *)PyExc_StandardError)->tp_clear((PyObject *)self); } static void error_dealloc(errorObject *self) { + PyObject_GC_UnTrack((PyObject *)self); error_clear(self); + PyMem_Free(self->codec); + CLEARPGRES(self->pgres); + return Py_TYPE(self)->tp_free((PyObject *)self); }