From 1888bf41c0dcdde6d6ef825393554121d88a69e1 Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Mon, 6 Jun 2011 23:47:13 +0100 Subject: [PATCH] Added patch for refcount bug in copy_from By Dave Malcolm. https://bugzilla.redhat.com/show_bug.cgi?id=711095 (slightly edited to increment the refcount before storing the pointer in the cursor). --- NEWS | 2 ++ psycopg/cursor_type.c | 10 ++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index c7b2aaac..7f0070cd 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,8 @@ What's new in psycopg 2.4.2 support was built (ticket #53). - Fixed escape for negative numbers prefixed by minus operator (ticket #57). + - Fixed refcount issue during copy. Reported and fixed by Dave + Malcolm (ticket #58, Red Hat Bug 711095). - Trying to execute concurrent operations on the same connection through concurrent green thread results in an error instead of a deadlock. diff --git a/psycopg/cursor_type.c b/psycopg/cursor_type.c index c18fb71d..0aa88c6b 100644 --- a/psycopg/cursor_type.c +++ b/psycopg/cursor_type.c @@ -1220,8 +1220,12 @@ _psyco_curs_has_read_check(PyObject* o, void* var) { if (PyObject_HasAttrString(o, "readline") && PyObject_HasAttrString(o, "read")) { - /* It's OK to store a borrowed reference, because it is only held for - * the duration of psyco_curs_copy_from. */ + /* This routine stores a borrowed reference. Although it is only held + * for the duration of psyco_curs_copy_from, nested invocations of + * Py_BEGIN_ALLOW_THREADS could surrender control to another thread, + * which could invoke the garbage collector. We thus need an + * INCREF/DECREF pair if we store this pointer in a GC object, such as + * a cursorObject */ *((PyObject**)var) = o; return 1; } @@ -1311,6 +1315,7 @@ psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs) Dprintf("psyco_curs_copy_from: query = %s", query); self->copysize = bufsize; + Py_INCREF(file); self->copyfile = file; if (pq_execute(self, query, 0) == 1) { @@ -1319,6 +1324,7 @@ psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs) } self->copyfile = NULL; + Py_DECREF(file); exit: PyMem_Free(quoted_delimiter);