diff options
| author | Daniele Varrazzo <daniele.varrazzo@gmail.com> | 2011-01-03 13:41:36 +0100 |
|---|---|---|
| committer | Daniele Varrazzo <daniele.varrazzo@gmail.com> | 2011-01-03 21:34:49 +0100 |
| commit | 5f6e77357567bfba2046bd9fd4b8a2d3ad009d87 (patch) | |
| tree | ed56fa0ea78c4a682acb2874492687cfe7220eb1 /psycopg/connection_int.c | |
| parent | 19ff51ae75914c2226888ac1a3ffecdc590d0ec7 (diff) | |
| download | psycopg2-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.c | 15 |
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; |
