From a39fb19eb9db28205510aff445214b6c8004b7d8 Mon Sep 17 00:00:00 2001 From: James Henstridge Date: Wed, 28 May 2008 09:00:36 +0800 Subject: [PATCH 1/9] * psycopg/connection_type.c: * psycopg/cursor_type.c: add support for cyclic GC. * psycopg/python.h: add definitions for Py_CLEAR() and Py_VISIT() for compatibility with old versions of Python. --- psycopg/connection_type.c | 28 ++++++++++++++++++-------- psycopg/cursor_type.c | 42 ++++++++++++++++++++++++++++----------- psycopg/python.h | 23 +++++++++++++++++++++ 3 files changed, 73 insertions(+), 20 deletions(-) diff --git a/psycopg/connection_type.c b/psycopg/connection_type.c index 3cdbf1fc..a7be6582 100644 --- a/psycopg/connection_type.c +++ b/psycopg/connection_type.c @@ -450,11 +450,11 @@ connection_dealloc(PyObject* obj) if (self->encoding) free(self->encoding); if (self->critical) free(self->critical); - Py_XDECREF(self->notice_list); - Py_XDECREF(self->notifies); - Py_XDECREF(self->async_cursor); - Py_XDECREF(self->string_types); - Py_XDECREF(self->binary_types); + Py_CLEAR(self->notice_list); + Py_CLEAR(self->notifies); + Py_CLEAR(self->async_cursor); + Py_CLEAR(self->string_types); + Py_CLEAR(self->binary_types); pthread_mutex_destroy(&(self->lock)); @@ -486,7 +486,7 @@ connection_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static void connection_del(PyObject* self) { - PyObject_Del(self); + PyObject_GC_Del(self); } static PyObject * @@ -497,6 +497,18 @@ connection_repr(connectionObject *self) self, self->dsn, self->closed); } +static int +connection_traverse(connectionObject *self, visitproc visit, void *arg) +{ + Py_VISIT(self->async_cursor); + Py_VISIT(self->notice_list); + Py_VISIT(self->notice_filter); + Py_VISIT(self->notifies); + Py_VISIT(self->string_types); + Py_VISIT(self->binary_types); + return 0; +} + /* object type */ @@ -530,10 +542,10 @@ PyTypeObject connectionType = { 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ connectionType_doc, /*tp_doc*/ - 0, /*tp_traverse*/ + (traverseproc)connection_traverse, /*tp_traverse*/ 0, /*tp_clear*/ 0, /*tp_richcompare*/ diff --git a/psycopg/cursor_type.c b/psycopg/cursor_type.c index 5b0cd026..03be9d90 100644 --- a/psycopg/cursor_type.c +++ b/psycopg/cursor_type.c @@ -1634,15 +1634,15 @@ cursor_dealloc(PyObject* obj) if (self->name) PyMem_Free(self->name); - Py_XDECREF((PyObject*)self->conn); - Py_XDECREF(self->casts); - Py_XDECREF(self->description); - Py_XDECREF(self->pgstatus); - Py_XDECREF(self->tuple_factory); - Py_XDECREF(self->tzinfo_factory); - Py_XDECREF(self->query); - Py_XDECREF(self->string_types); - Py_XDECREF(self->binary_types); + Py_CLEAR(self->conn); + Py_CLEAR(self->casts); + Py_CLEAR(self->description); + Py_CLEAR(self->pgstatus); + Py_CLEAR(self->tuple_factory); + Py_CLEAR(self->tzinfo_factory); + Py_CLEAR(self->query); + Py_CLEAR(self->string_types); + Py_CLEAR(self->binary_types); IFCLEARPGRES(self->pgres); @@ -1675,7 +1675,7 @@ cursor_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static void cursor_del(PyObject* self) { - PyObject_Del(self); + PyObject_GC_Del(self); } static PyObject * @@ -1685,6 +1685,23 @@ cursor_repr(cursorObject *self) "", self, self->closed); } +static int +cursor_traverse(cursorObject *self, visitproc visit, void *arg) +{ + Py_VISIT(self->conn); + Py_VISIT(self->description); + Py_VISIT(self->pgstatus); + Py_VISIT(self->casts); + Py_VISIT(self->caster); + Py_VISIT(self->copyfile); + Py_VISIT(self->tuple_factory); + Py_VISIT(self->tzinfo_factory); + Py_VISIT(self->query); + Py_VISIT(self->string_types); + Py_VISIT(self->binary_types); + return 0; +} + /* object type */ @@ -1714,10 +1731,11 @@ PyTypeObject cursorType = { 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_ITER, /*tp_flags*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_ITER | + Py_TPFLAGS_HAVE_GC, /*tp_flags*/ cursorType_doc, /*tp_doc*/ - 0, /*tp_traverse*/ + (traverseproc)cursor_traverse, /*tp_traverse*/ 0, /*tp_clear*/ 0, /*tp_richcompare*/ diff --git a/psycopg/python.h b/psycopg/python.h index 84bacaa2..13d6ce79 100644 --- a/psycopg/python.h +++ b/psycopg/python.h @@ -41,4 +41,27 @@ #define freefunc destructor #endif +/* Py_VISIT and Py_CLEAR introduced in Python 2.4 */ +#ifndef Py_VISIT +#define Py_VISIT(op) \ + do { \ + if (op) { \ + int vret = visit((op), arg); \ + if (vret) \ + return vret; \ + } \ + } while (0) +#endif + +#ifndef Py_CLEAR +#define Py_CLEAR(op) \ + do { \ + if (op) { \ + PyObject *tmp = (PyObject *)(op); \ + (op) = NULL; \ + Py_DECREF(tmp); \ + } \ + } while (0) +#endif + #endif /* !defined(PSYCOPG_PYTHON_H) */ From bbd101bb7e14da4242b415a0b33908a96adcacc4 Mon Sep 17 00:00:00 2001 From: James Henstridge Date: Wed, 28 May 2008 17:22:40 +0800 Subject: [PATCH 2/9] * psycopg/typecast.c (typecast_traverse): implement cyclic GC traversal for typecasters. --- ChangeLog | 12 ++++++++++++ psycopg/typecast.c | 36 ++++++++++++++++++++++++++++-------- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5367d35f..b81b422e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2008-05-28 James Henstridge + + * psycopg/typecast.c (typecast_traverse): implement cyclic GC + traversal for typecasters. + + * psycopg/connection_type.c: + * psycopg/cursor_type.c: add support for cyclic GC traversal (no + support for clearing). + + * psycopg/python.h: add definitions for Py_CLEAR() and Py_VISIT() + for compatibility with old versions of Python. + 2008-05-19 Federico Di Gregorio * psycopg/cursor_type.c: fixed memory leak in .executemany(); on diff --git a/psycopg/typecast.c b/psycopg/typecast.c index 86e21494..f7869608 100644 --- a/psycopg/typecast.c +++ b/psycopg/typecast.c @@ -382,11 +382,28 @@ typecast_dealloc(PyObject *obj) { typecastObject *self = (typecastObject*)obj; - Py_XDECREF(self->values); - Py_XDECREF(self->name); - Py_XDECREF(self->pcast); + Py_CLEAR(self->values); + Py_CLEAR(self->name); + Py_CLEAR(self->pcast); - PyObject_Del(self); + obj->ob_type->tp_free(obj); +} + +static int +typecast_traverse(PyObject *obj, visitproc visit, void *arg) +{ + typecastObject *self = (typecastObject*)obj; + + Py_VISIT(self->values); + Py_VISIT(self->name); + Py_VISIT(self->pcast); + return 0; +} + +static void +typecast_del(void *self) +{ + PyObject_GC_Del(self); } static PyObject * @@ -427,10 +444,11 @@ PyTypeObject typecastType = { 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ - Py_TPFLAGS_HAVE_RICHCOMPARE, /*tp_flags*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_RICHCOMPARE | + Py_TPFLAGS_HAVE_GC, /*tp_flags*/ "psycopg type-casting object", /*tp_doc*/ - 0, /*tp_traverse*/ + typecast_traverse, /*tp_traverse*/ 0, /*tp_clear*/ typecast_richcompare, /*tp_richcompare*/ @@ -454,7 +472,7 @@ PyTypeObject typecastType = { 0, /*tp_init*/ 0, /*tp_alloc will be set to PyType_GenericAlloc in module init*/ 0, /*tp_new*/ - 0, /*tp_free Low-level free-memory routine */ + typecast_del, /*tp_free Low-level free-memory routine */ 0, /*tp_is_gc For PyObject_IS_GC */ 0, /*tp_bases*/ 0, /*tp_mro method resolution order */ @@ -468,7 +486,7 @@ typecast_new(PyObject *name, PyObject *values, PyObject *cast, PyObject *base) { typecastObject *obj; - obj = PyObject_NEW(typecastObject, &typecastType); + obj = PyObject_GC_New(typecastObject, &typecastType); if (obj == NULL) return NULL; Dprintf("typecast_new: new type at = %p, refcnt = " FORMAT_CODE_PY_SSIZE_T, @@ -498,6 +516,8 @@ typecast_new(PyObject *name, PyObject *values, PyObject *cast, PyObject *base) obj->pcast = cast; } + PyObject_GC_Track(obj); + Dprintf("typecast_new: typecast object created at %p", obj); return (PyObject *)obj; From 26693621ef29add6f86354a689dede000d9d962e Mon Sep 17 00:00:00 2001 From: James Henstridge Date: Wed, 28 May 2008 17:45:37 +0800 Subject: [PATCH 3/9] * psycopg/cursor_type.c (cursor_setup): incref before setting attributes, to make things GC-safe. * psycopg/cursor_int.c (curs_reset): make clearing of description and casts attributes GC-safe. --- ChangeLog | 6 ++++++ psycopg/cursor_int.c | 8 ++++++-- psycopg/cursor_type.c | 6 +++--- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index b81b422e..2a58f1f6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,11 @@ 2008-05-28 James Henstridge + * psycopg/cursor_type.c (cursor_setup): incref before setting + attributes, to make things GC-safe. + + * psycopg/cursor_int.c (curs_reset): make clearing of description + and casts attributes GC-safe. + * psycopg/typecast.c (typecast_traverse): implement cyclic GC traversal for typecasters. diff --git a/psycopg/cursor_int.c b/psycopg/cursor_int.c index 483e2c44..9d3c861c 100644 --- a/psycopg/cursor_int.c +++ b/psycopg/cursor_int.c @@ -34,15 +34,19 @@ void curs_reset(cursorObject *self) { + PyObject *tmp; + /* initialize some variables to default values */ self->notuples = 1; self->rowcount = -1; self->row = 0; - Py_XDECREF(self->description); + tmp = self->description; Py_INCREF(Py_None); self->description = Py_None; + Py_XDECREF(tmp); - Py_XDECREF(self->casts); + tmp = self->casts; self->casts = NULL; + Py_XDECREF(tmp); } diff --git a/psycopg/cursor_type.c b/psycopg/cursor_type.c index 03be9d90..1ff5b962 100644 --- a/psycopg/cursor_type.c +++ b/psycopg/cursor_type.c @@ -1590,8 +1590,8 @@ cursor_setup(cursorObject *self, connectionObject *conn, const char *name) "argument 1 must be subclass of psycopg2._psycopg.connection"); return 1; } */ + Py_INCREF(conn); self->conn = conn; - Py_INCREF((PyObject*)self->conn); self->closed = 0; self->mark = conn->mark; @@ -1607,6 +1607,7 @@ cursor_setup(cursorObject *self, connectionObject *conn, const char *name) self->string_types = NULL; self->binary_types = NULL; + Py_INCREF(Py_None); self->description = Py_None; Py_INCREF(Py_None); self->pgstatus = Py_None; @@ -1614,11 +1615,10 @@ cursor_setup(cursorObject *self, connectionObject *conn, const char *name) self->tuple_factory = Py_None; Py_INCREF(Py_None); self->query = Py_None; - Py_INCREF(Py_None); /* default tzinfo factory */ + Py_INCREF(pyPsycopgTzFixedOffsetTimezone); self->tzinfo_factory = pyPsycopgTzFixedOffsetTimezone; - Py_INCREF(self->tzinfo_factory); Dprintf("cursor_setup: good cursor object at %p, refcnt = " FORMAT_CODE_PY_SSIZE_T, From fd538a8b17e741c611ac0519b2e107cc4fd39fdb Mon Sep 17 00:00:00 2001 From: James Henstridge Date: Tue, 1 Jul 2008 09:34:51 +0800 Subject: [PATCH 4/9] * psycopg/adapter_list.c (list_traverse): add cyclic GC traversal for list adapters. --- ChangeLog | 5 +++++ psycopg/adapter_list.c | 16 +++++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2a58f1f6..e594ef27 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2008-07-01 James Henstridge + + * psycopg/adapter_list.c (list_traverse): add cyclic GC traversal + for list adapters. + 2008-05-28 James Henstridge * psycopg/cursor_type.c (cursor_setup): incref before setting diff --git a/psycopg/adapter_list.c b/psycopg/adapter_list.c index b6022bd5..a1a9f598 100644 --- a/psycopg/adapter_list.c +++ b/psycopg/adapter_list.c @@ -179,6 +179,16 @@ list_setup(listObject *self, PyObject *obj, const char *enc) return 0; } +static int +list_traverse(PyObject *obj, visitproc visit, void *arg) +{ + listObject *self = (listObject *)obj; + + Py_VISIT(self->wrapped); + Py_VISIT(self->connection); + return 0; +} + static void list_dealloc(PyObject* obj) { @@ -215,7 +225,7 @@ list_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static void list_del(PyObject* self) { - PyObject_Del(self); + PyObject_GC_Del(self); } static PyObject * @@ -253,11 +263,11 @@ PyTypeObject listType = { 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ listType_doc, /*tp_doc*/ - 0, /*tp_traverse*/ + list_traverse, /*tp_traverse*/ 0, /*tp_clear*/ 0, /*tp_richcompare*/ From 47d2414e3225aa5863663463cbfdb482e6820aa3 Mon Sep 17 00:00:00 2001 From: James Henstridge Date: Tue, 1 Jul 2008 09:57:16 +0800 Subject: [PATCH 5/9] * psycopg/adapter_asis.c (asis_traverse): add cyclic GC traversal for AsIs adapters. --- ChangeLog | 3 +++ psycopg/adapter_asis.c | 13 ++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index e594ef27..f068d978 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2008-07-01 James Henstridge + * psycopg/adapter_asis.c (asis_traverse): add cyclic GC traversal + for AsIs adapters. + * psycopg/adapter_list.c (list_traverse): add cyclic GC traversal for list adapters. diff --git a/psycopg/adapter_asis.c b/psycopg/adapter_asis.c index 0e64eb5d..3fc9c560 100644 --- a/psycopg/adapter_asis.c +++ b/psycopg/adapter_asis.c @@ -106,6 +106,13 @@ asis_setup(asisObject *self, PyObject *obj) return 0; } +static int +asis_traverse(asisObject *self, visitproc visit, void *arg) +{ + Py_VISIT(self->wrapped); + return 0; +} + static void asis_dealloc(PyObject* obj) { @@ -141,7 +148,7 @@ asis_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static void asis_del(PyObject* self) { - PyObject_Del(self); + PyObject_GC_Del(self); } static PyObject * @@ -183,10 +190,10 @@ PyTypeObject asisType = { 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ asisType_doc, /*tp_doc*/ - 0, /*tp_traverse*/ + (traverseproc)asis_traverse, /*tp_traverse*/ 0, /*tp_clear*/ 0, /*tp_richcompare*/ From 590542e973ebc112e1e7e6f20fca28d7c92bcdb6 Mon Sep 17 00:00:00 2001 From: James Henstridge Date: Tue, 1 Jul 2008 11:59:25 +0800 Subject: [PATCH 6/9] * psycopg/adapter_binary.c (binary_traverse): add cyclic GC traversal for binary adapters. --- ChangeLog | 3 +++ psycopg/adapter_binary.c | 17 ++++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index f068d978..089950d0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2008-07-01 James Henstridge + * psycopg/adapter_binary.c (binary_traverse): add cyclic GC + traversal for binary adapters. + * psycopg/adapter_asis.c (asis_traverse): add cyclic GC traversal for AsIs adapters. diff --git a/psycopg/adapter_binary.c b/psycopg/adapter_binary.c index 1fb9d40f..205a5e22 100644 --- a/psycopg/adapter_binary.c +++ b/psycopg/adapter_binary.c @@ -266,6 +266,17 @@ binary_setup(binaryObject *self, PyObject *str) return 0; } +static int +binary_traverse(PyObject *obj, visitproc visit, void *arg) +{ + binaryObject *self = (binaryObject *)obj; + + Py_VISIT(self->wrapped); + Py_VISIT(self->buffer); + Py_VISIT(self->conn); + return 0; +} + static void binary_dealloc(PyObject* obj) { @@ -303,7 +314,7 @@ binary_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static void binary_del(PyObject* self) { - PyObject_Del(self); + PyObject_GC_Del(self); } static PyObject * @@ -341,11 +352,11 @@ PyTypeObject binaryType = { 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ binaryType_doc, /*tp_doc*/ - 0, /*tp_traverse*/ + binary_traverse, /*tp_traverse*/ 0, /*tp_clear*/ 0, /*tp_richcompare*/ From e0287c0db4ceb3daca64b2e3dd32397b357b7e3c Mon Sep 17 00:00:00 2001 From: James Henstridge Date: Fri, 18 Jul 2008 17:42:31 +0800 Subject: [PATCH 7/9] * psycopg/adapter_qstring.c (qstring_traverse): add cyclic GC traversal for quoted string adapters. * psycopg/adapter_pboolean.c (pboolean_traverse): add cyclic GC traversal for boolean adapters. * psycopg/adapter_mxdatetime.c (mxdatetime_traverse): add cyclic GC traversal for mxdatetime adapters. * psycopg/adapter_datetime.c (pydatetime_traverse): add cyclic GC traversal for datetime adapters. --- ChangeLog | 14 ++++++++++++++ psycopg/adapter_datetime.c | 15 ++++++++++++--- psycopg/adapter_mxdatetime.c | 15 ++++++++++++--- psycopg/adapter_pboolean.c | 15 ++++++++++++--- psycopg/adapter_qstring.c | 17 ++++++++++++++--- 5 files changed, 64 insertions(+), 12 deletions(-) diff --git a/ChangeLog b/ChangeLog index 089950d0..024f2a17 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2008-07-18 James Henstridge + + * psycopg/adapter_qstring.c (qstring_traverse): add cyclic GC + traversal for quoted string adapters. + + * psycopg/adapter_pboolean.c (pboolean_traverse): add cyclic GC + traversal for boolean adapters. + + * psycopg/adapter_mxdatetime.c (mxdatetime_traverse): add cyclic + GC traversal for mxdatetime adapters. + + * psycopg/adapter_datetime.c (pydatetime_traverse): add cyclic GC + traversal for datetime adapters. + 2008-07-01 James Henstridge * psycopg/adapter_binary.c (binary_traverse): add cyclic GC diff --git a/psycopg/adapter_datetime.c b/psycopg/adapter_datetime.c index e9fcc1e1..322e019d 100644 --- a/psycopg/adapter_datetime.c +++ b/psycopg/adapter_datetime.c @@ -140,6 +140,15 @@ pydatetime_setup(pydatetimeObject *self, PyObject *obj, int type) return 0; } +static int +pydatetime_traverse(PyObject *obj, visitproc visit, void *arg) +{ + pydatetimeObject *self = (pydatetimeObject *)obj; + + Py_VISIT(self->wrapped); + return 0; +} + static void pydatetime_dealloc(PyObject* obj) { @@ -174,7 +183,7 @@ pydatetime_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static void pydatetime_del(PyObject* self) { - PyObject_Del(self); + PyObject_GC_Del(self); } static PyObject * @@ -213,11 +222,11 @@ PyTypeObject pydatetimeType = { 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ pydatetimeType_doc, /*tp_doc*/ - 0, /*tp_traverse*/ + pydatetime_traverse, /*tp_traverse*/ 0, /*tp_clear*/ 0, /*tp_richcompare*/ diff --git a/psycopg/adapter_mxdatetime.c b/psycopg/adapter_mxdatetime.c index 48ead92e..8750b1bf 100644 --- a/psycopg/adapter_mxdatetime.c +++ b/psycopg/adapter_mxdatetime.c @@ -162,6 +162,15 @@ mxdatetime_setup(mxdatetimeObject *self, PyObject *obj, int type) return 0; } +static int +mxdatetime_traverse(PyObject *obj, visitproc visit, void *arg) +{ + mxdatetimeObject *self = (mxdatetimeObject *)obj; + + Py_VISIT(self->wrapped); + return 0; +} + static void mxdatetime_dealloc(PyObject* obj) { @@ -198,7 +207,7 @@ mxdatetime_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static void mxdatetime_del(PyObject* self) { - PyObject_Del(self); + PyObject_GC_Del(self); } static PyObject * @@ -237,11 +246,11 @@ PyTypeObject mxdatetimeType = { 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ mxdatetimeType_doc, /*tp_doc*/ - 0, /*tp_traverse*/ + mxdatetime_traverse, /*tp_traverse*/ 0, /*tp_clear*/ 0, /*tp_richcompare*/ diff --git a/psycopg/adapter_pboolean.c b/psycopg/adapter_pboolean.c index 05d1d046..29e3410e 100644 --- a/psycopg/adapter_pboolean.c +++ b/psycopg/adapter_pboolean.c @@ -116,6 +116,15 @@ pboolean_setup(pbooleanObject *self, PyObject *obj) return 0; } +static int +pboolean_traverse(PyObject *obj, visitproc visit, void *arg) +{ + pbooleanObject *self = (pbooleanObject *)obj; + + Py_VISIT(self->wrapped); + return 0; +} + static void pboolean_dealloc(PyObject* obj) { @@ -151,7 +160,7 @@ pboolean_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static void pboolean_del(PyObject* self) { - PyObject_Del(self); + PyObject_GC_Del(self); } static PyObject * @@ -194,10 +203,10 @@ PyTypeObject pbooleanType = { 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ pbooleanType_doc, /*tp_doc*/ - 0, /*tp_traverse*/ + pboolean_traverse, /*tp_traverse*/ 0, /*tp_clear*/ 0, /*tp_richcompare*/ diff --git a/psycopg/adapter_qstring.c b/psycopg/adapter_qstring.c index 3684039b..32185fef 100644 --- a/psycopg/adapter_qstring.c +++ b/psycopg/adapter_qstring.c @@ -290,6 +290,17 @@ qstring_setup(qstringObject *self, PyObject *str, const char *enc) return 0; } +static int +qstring_traverse(PyObject *obj, visitproc visit, void *arg) +{ + qstringObject *self = (qstringObject *)obj; + + Py_VISIT(self->wrapped); + Py_VISIT(self->buffer); + Py_VISIT(self->conn); + return 0; +} + static void qstring_dealloc(PyObject* obj) { @@ -330,7 +341,7 @@ qstring_new(PyTypeObject *type, PyObject *args, PyObject *kwds) static void qstring_del(PyObject* self) { - PyObject_Del(self); + PyObject_GC_Del(self); } static PyObject * @@ -369,11 +380,11 @@ PyTypeObject qstringType = { 0, /*tp_setattro*/ 0, /*tp_as_buffer*/ - Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, /*tp_flags*/ + Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE|Py_TPFLAGS_HAVE_GC, /*tp_flags*/ qstringType_doc, /*tp_doc*/ - 0, /*tp_traverse*/ + qstring_traverse, /*tp_traverse*/ 0, /*tp_clear*/ 0, /*tp_richcompare*/ From 2273b79be912ab46e58418b077d50d59d5e4511c Mon Sep 17 00:00:00 2001 From: James Henstridge Date: Mon, 21 Jul 2008 13:41:54 +0800 Subject: [PATCH 8/9] Use Py_CLEAR() in a few more places, and do INCREF's before setting struct members rather than afterwards. --- psycopg/adapter_asis.c | 4 ++-- psycopg/adapter_binary.c | 8 ++++---- psycopg/adapter_datetime.c | 4 ++-- psycopg/adapter_list.c | 10 +++++----- psycopg/adapter_mxdatetime.c | 4 ++-- psycopg/adapter_pboolean.c | 4 ++-- psycopg/adapter_qstring.c | 12 ++++++------ psycopg/cursor_type.c | 2 +- 8 files changed, 24 insertions(+), 24 deletions(-) diff --git a/psycopg/adapter_asis.c b/psycopg/adapter_asis.c index 3fc9c560..2ad6ef56 100644 --- a/psycopg/adapter_asis.c +++ b/psycopg/adapter_asis.c @@ -96,8 +96,8 @@ asis_setup(asisObject *self, PyObject *obj) self, ((PyObject *)self)->ob_refcnt ); + Py_INCREF(obj); self->wrapped = obj; - Py_INCREF(self->wrapped); Dprintf("asis_setup: good asis object at %p, refcnt = " FORMAT_CODE_PY_SSIZE_T, @@ -118,7 +118,7 @@ asis_dealloc(PyObject* obj) { asisObject *self = (asisObject *)obj; - Py_XDECREF(self->wrapped); + Py_CLEAR(self->wrapped); Dprintf("asis_dealloc: deleted asis object at %p, refcnt = " FORMAT_CODE_PY_SSIZE_T, diff --git a/psycopg/adapter_binary.c b/psycopg/adapter_binary.c index 205a5e22..306c9e52 100644 --- a/psycopg/adapter_binary.c +++ b/psycopg/adapter_binary.c @@ -257,8 +257,8 @@ binary_setup(binaryObject *self, PyObject *str) self->buffer = NULL; self->conn = NULL; + Py_INCREF(str); self->wrapped = str; - Py_INCREF(self->wrapped); Dprintf("binary_setup: good binary object at %p, refcnt = " FORMAT_CODE_PY_SSIZE_T, @@ -282,9 +282,9 @@ binary_dealloc(PyObject* obj) { binaryObject *self = (binaryObject *)obj; - Py_XDECREF(self->wrapped); - Py_XDECREF(self->buffer); - Py_XDECREF(self->conn); + Py_CLEAR(self->wrapped); + Py_CLEAR(self->buffer); + Py_CLEAR(self->conn); Dprintf("binary_dealloc: deleted binary object at %p, refcnt = " FORMAT_CODE_PY_SSIZE_T, diff --git a/psycopg/adapter_datetime.c b/psycopg/adapter_datetime.c index 322e019d..bf337ee7 100644 --- a/psycopg/adapter_datetime.c +++ b/psycopg/adapter_datetime.c @@ -131,8 +131,8 @@ pydatetime_setup(pydatetimeObject *self, PyObject *obj, int type) self, ((PyObject *)self)->ob_refcnt); self->type = type; + Py_INCREF(obj); self->wrapped = obj; - Py_INCREF(self->wrapped); Dprintf("pydatetime_setup: good pydatetime object at %p, refcnt = " FORMAT_CODE_PY_SSIZE_T, @@ -154,7 +154,7 @@ pydatetime_dealloc(PyObject* obj) { pydatetimeObject *self = (pydatetimeObject *)obj; - Py_XDECREF(self->wrapped); + Py_CLEAR(self->wrapped); Dprintf("mpydatetime_dealloc: deleted pydatetime object at %p, " "refcnt = " FORMAT_CODE_PY_SSIZE_T, obj, obj->ob_refcnt); diff --git a/psycopg/adapter_list.c b/psycopg/adapter_list.c index a1a9f598..2d26c39c 100644 --- a/psycopg/adapter_list.c +++ b/psycopg/adapter_list.c @@ -108,9 +108,9 @@ list_prepare(listObject *self, PyObject *args) reference to it; we'll need it during the recursive adapt() call (the encoding is here for a future expansion that will make .getquoted() work even without a connection to the backend. */ - Py_XDECREF(self->connection); + Py_CLEAR(self->connection); + Py_INCREF(conn); self->connection = (PyObject*)conn; - Py_INCREF(self->connection); Py_INCREF(Py_None); return Py_None; @@ -169,8 +169,8 @@ list_setup(listObject *self, PyObject *obj, const char *enc) if (enc) self->encoding = strdup(enc); self->connection = NULL; + Py_INCREF(obj); self->wrapped = obj; - Py_INCREF(self->wrapped); Dprintf("list_setup: good list object at %p, refcnt = " FORMAT_CODE_PY_SSIZE_T, @@ -194,8 +194,8 @@ list_dealloc(PyObject* obj) { listObject *self = (listObject *)obj; - Py_XDECREF(self->wrapped); - Py_XDECREF(self->connection); + Py_CLEAR(self->wrapped); + Py_CLEAR(self->connection); if (self->encoding) free(self->encoding); Dprintf("list_dealloc: deleted list object at %p, " diff --git a/psycopg/adapter_mxdatetime.c b/psycopg/adapter_mxdatetime.c index 8750b1bf..92b21819 100644 --- a/psycopg/adapter_mxdatetime.c +++ b/psycopg/adapter_mxdatetime.c @@ -152,8 +152,8 @@ mxdatetime_setup(mxdatetimeObject *self, PyObject *obj, int type) ); self->type = type; + Py_INCREF(obj); self->wrapped = obj; - Py_INCREF(self->wrapped); Dprintf("mxdatetime_setup: good mxdatetime object at %p, refcnt = " FORMAT_CODE_PY_SSIZE_T, @@ -176,7 +176,7 @@ mxdatetime_dealloc(PyObject* obj) { mxdatetimeObject *self = (mxdatetimeObject *)obj; - Py_XDECREF(self->wrapped); + Py_CLEAR(self->wrapped); Dprintf("mxdatetime_dealloc: deleted mxdatetime object at %p, refcnt = " FORMAT_CODE_PY_SSIZE_T, diff --git a/psycopg/adapter_pboolean.c b/psycopg/adapter_pboolean.c index 29e3410e..1ce80dd9 100644 --- a/psycopg/adapter_pboolean.c +++ b/psycopg/adapter_pboolean.c @@ -106,8 +106,8 @@ pboolean_setup(pbooleanObject *self, PyObject *obj) self, ((PyObject *)self)->ob_refcnt ); + Py_INCREF(obj); self->wrapped = obj; - Py_INCREF(self->wrapped); Dprintf("pboolean_setup: good pboolean object at %p, refcnt = " FORMAT_CODE_PY_SSIZE_T, @@ -130,7 +130,7 @@ pboolean_dealloc(PyObject* obj) { pbooleanObject *self = (pbooleanObject *)obj; - Py_XDECREF(self->wrapped); + Py_CLEAR(self->wrapped); Dprintf("pboolean_dealloc: deleted pboolean object at %p, refcnt = " FORMAT_CODE_PY_SSIZE_T, diff --git a/psycopg/adapter_qstring.c b/psycopg/adapter_qstring.c index 32185fef..1fb510b3 100644 --- a/psycopg/adapter_qstring.c +++ b/psycopg/adapter_qstring.c @@ -216,10 +216,10 @@ qstring_prepare(qstringObject *self, PyObject *args) Dprintf("qstring_prepare: set encoding to %s", conn->encoding); } - Py_XDECREF(self->conn); + Py_CLEAR(self->conn); if (conn) { + Py_INCREF(conn); self->conn = (PyObject*)conn; - Py_INCREF(self->conn); } Py_INCREF(Py_None); @@ -280,8 +280,8 @@ qstring_setup(qstringObject *self, PyObject *str, const char *enc) /* FIXME: remove this orrible strdup */ if (enc) self->encoding = strdup(enc); + Py_INCREF(str); self->wrapped = str; - Py_INCREF(self->wrapped); Dprintf("qstring_setup: good qstring object at %p, refcnt = " FORMAT_CODE_PY_SSIZE_T, @@ -306,9 +306,9 @@ qstring_dealloc(PyObject* obj) { qstringObject *self = (qstringObject *)obj; - Py_XDECREF(self->wrapped); - Py_XDECREF(self->buffer); - Py_XDECREF(self->conn); + Py_CLEAR(self->wrapped); + Py_CLEAR(self->buffer); + Py_CLEAR(self->conn); if (self->encoding) free(self->encoding); diff --git a/psycopg/cursor_type.c b/psycopg/cursor_type.c index 1ff5b962..8000816e 100644 --- a/psycopg/cursor_type.c +++ b/psycopg/cursor_type.c @@ -1688,7 +1688,7 @@ cursor_repr(cursorObject *self) static int cursor_traverse(cursorObject *self, visitproc visit, void *arg) { - Py_VISIT(self->conn); + Py_VISIT((PyObject *)self->conn); Py_VISIT(self->description); Py_VISIT(self->pgstatus); Py_VISIT(self->casts); From a2f3e4a3acd58afb09438be186e5fb0a98620820 Mon Sep 17 00:00:00 2001 From: James Henstridge Date: Wed, 23 Jul 2008 16:57:10 +0800 Subject: [PATCH 9/9] * psycopg/lobject_type.c (lobject_setup): use FORMAT_CODE_PY_SSIZE_T in Dprintf() call for 64-bit compatibility when using Python 2.5 or later. (lobject_dealloc): same here. --- ChangeLog | 7 +++++++ psycopg/lobject_type.c | 8 ++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0344a6de..dd6705f8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2008-07-23 James Henstridge + + * psycopg/lobject_type.c (lobject_setup): use + FORMAT_CODE_PY_SSIZE_T in Dprintf() call for 64-bit compatibility + when using Python 2.5 or later. + (lobject_dealloc): same here. + 2008-07-18 James Henstridge * psycopg/adapter_qstring.c (qstring_traverse): add cyclic GC diff --git a/psycopg/lobject_type.c b/psycopg/lobject_type.c index ca0a82ba..c4386bf6 100644 --- a/psycopg/lobject_type.c +++ b/psycopg/lobject_type.c @@ -282,8 +282,8 @@ lobject_setup(lobjectObject *self, connectionObject *conn, if (lobject_open(self, conn, oid, mode, new_oid, new_file) == -1) return -1; - Dprintf("lobject_setup: good lobject object at %p, refcnt = %d", - self, ((PyObject *)self)->ob_refcnt); + Dprintf("lobject_setup: good lobject object at %p, refcnt = " + FORMAT_CODE_PY_SSIZE_T, self, ((PyObject *)self)->ob_refcnt); Dprintf("lobject_setup: oid = %d, fd = %d", self->oid, self->fd); return 0; } @@ -297,8 +297,8 @@ lobject_dealloc(PyObject* obj) PyErr_Print(); Py_XDECREF((PyObject*)self->conn); - Dprintf("lobject_dealloc: deleted lobject object at %p, refcnt = %d", - obj, obj->ob_refcnt); + Dprintf("lobject_dealloc: deleted lobject object at %p, refcnt = " + FORMAT_CODE_PY_SSIZE_T, obj, obj->ob_refcnt); obj->ob_type->tp_free(obj); }