Re: visit_decref: Assertion `gc->gc.gc_refs != 0' failed.
Jan Urbański <[email protected]> Sat, 27 Mar 2010 03:17:50 +0100
| Newsgroups | gmane.comp.python.db.psycopg.devel |
|---|---|
| Message-ID | <[email protected]> |
On 27/03/10 01:12, Jan Urbański wrote:
> On 23/03/10 16:39, Michael Tharp wrote:
>> Seeing python bomb out on a GC-related assertion during some heavy load
>> testing:
>>
>> #3 0x000000000048bd2c in visit_decref (op=0x7f7b78037c58,
>> data=<value optimized out>) at Modules/gcmodule.c:275
>> __PRETTY_FUNCTION__ = "visit_decref"
> could you provide a self-contained test case? I'm getting a very similar
> segfault and I'm not sure it's because of my patches to psycopg2 or
> would this happen in a vanilla build as well
Here's a patch that fixes my problem. The issue seemed to be that
psycopg2 was storing the asynchronous cursor in conn->async_cursor, and
then the connection_traverse function was visiting conn->async_cursor
and unreffing it, after which the cursor itself was being unreffed and
that was messing up reference counting.
I was able to trigger an assertion error using a Py_DEBUG build of
Python2.5 and the following script:
import psycopg2
import tests
conn = psycopg2.connect(tests.dsn)
cur = conn.cursor()
cur.execute("select 1", async=True)
del conn
Results:
python: Modules/gcmodule.c:276: visit_decref: Assertion `gc->gc.gc_refs
!= 0' failed.
Aborted
On a non-debug build I couldn't make it error, but compiling psycopg2
with PSYCOPG_DEBUG and then looking at the results of running this
script with PSYCOPG_DEBUG=1 I see:
[14619] connection_dealloc: deleted connection object at 0xb7667824,
refcnt = 0
[14619] cursor_dealloc: deleted cursor object at 0x93c1b8c, refcnt = -1
Which clearly is wrong.
I guess you're not using async cursors, so this might not fix your
problem, but it fixes mine so until you send in a reproducible testcase
my interest is significantly lower ;)
Jan
_______________________________________________
Psycopg mailing list
Psycopg-IAPFreCvJWPBWskQ1e/[email protected]
http://lists.initd.org/mailman/listinfo/psycopg
0001-Ref-the-async-cursor-before-storing-it-in-the-connec.patch
(text/x-diff, 1.3 KB)
From 9e2866e52845bb88a993d92115819bb7c44f31be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Urba=C5=84ski?= <[email protected]> Date: Sat, 27 Mar 2010 03:17:22 +0100 Subject: [PATCH] Ref the async cursor before storing it in the connection --- psycopg/cursor_type.c | 1 + psycopg/pqpath.c | 1 + 2 files changed, 2 insertions(+), 0 deletions(-) diff --git a/psycopg/cursor_type.c b/psycopg/cursor_type.c index 4c66a06..bc7c4e9 100644 --- a/psycopg/cursor_type.c +++ b/psycopg/cursor_type.c @@ -1517,6 +1517,7 @@ psyco_curs_isready(cursorObject *self, PyObject *args) Py_BEGIN_ALLOW_THREADS; pthread_mutex_lock(&(self->conn->lock)); self->pgres = PQgetResult(self->conn->pgconn); + Py_XDECREF(self->conn->async_cursor); self->conn->async_cursor = NULL; pthread_mutex_unlock(&(self->conn->lock)); Py_END_ALLOW_THREADS; diff --git a/psycopg/pqpath.c b/psycopg/pqpath.c index 8b0e134..835859f 100644 --- a/psycopg/pqpath.c +++ b/psycopg/pqpath.c @@ -706,6 +706,7 @@ pq_execute(cursorObject *curs, const char *query, int async) if (pq_fetch(curs) == -1) return -1; } else { + //Py_INCREF(curs); curs->conn->async_cursor = (PyObject*)curs; } -- 1.7.0