summaryrefslogtreecommitdiff
path: root/psycopg/connection_int.c
diff options
context:
space:
mode:
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>2011-01-03 13:41:36 +0100
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>2011-01-03 21:34:49 +0100
commit5f6e77357567bfba2046bd9fd4b8a2d3ad009d87 (patch)
treeed56fa0ea78c4a682acb2874492687cfe7220eb1 /psycopg/connection_int.c
parent19ff51ae75914c2226888ac1a3ffecdc590d0ec7 (diff)
downloadpsycopg2-5f6e77357567bfba2046bd9fd4b8a2d3ad009d87.tar.gz
Broken circular reference in async execution
If a connection is destroyed before an async operation is completed, the `async_cursor` member creates a reference loop, leaving the connection and the cursor alive. `async_cursor` is now a weak reference.
Diffstat (limited to 'psycopg/connection_int.c')
-rw-r--r--psycopg/connection_int.c15
1 files changed, 12 insertions, 3 deletions
diff --git a/psycopg/connection_int.c b/psycopg/connection_int.c
index 8451b45..9ccc11d 100644
--- a/psycopg/connection_int.c
+++ b/psycopg/connection_int.c
@@ -752,7 +752,17 @@ conn_poll(connectionObject *self)
if (res == PSYCO_POLL_OK && self->async_cursor) {
/* An async query has just finished: parse the tuple in the
* target cursor. */
- cursorObject *curs = (cursorObject *)self->async_cursor;
+ cursorObject *curs;
+ PyObject *py_curs = PyWeakref_GetObject(self->async_cursor);
+ if (Py_None == py_curs) {
+ pq_clear_async(self);
+ PyErr_SetString(InterfaceError,
+ "the asynchronous cursor has disappeared");
+ res = PSYCO_POLL_ERROR;
+ break;
+ }
+
+ curs = (cursorObject *)py_curs;
IFCLEARPGRES(curs->pgres);
curs->pgres = pq_get_last_result(self);
@@ -764,8 +774,7 @@ conn_poll(connectionObject *self)
}
/* We have finished with our async_cursor */
- Py_XDECREF(self->async_cursor);
- self->async_cursor = NULL;
+ Py_CLEAR(self->async_cursor);
}
break;