diff options
| author | Daniele Varrazzo <daniele.varrazzo@gmail.com> | 2012-10-11 22:25:59 +0100 |
|---|---|---|
| committer | Daniele Varrazzo <daniele.varrazzo@gmail.com> | 2012-10-11 22:26:51 +0100 |
| commit | 5fbf3ef147046548031896b49a27a21d94efae30 (patch) | |
| tree | 00710eb709a08041f80a326b909d7136347e1626 /psycopg | |
| parent | ee763e0f47802232000293b3e4e33d87f7d19720 (diff) | |
| parent | b61a2a34c40e9b6e8774178e553a2e81eb889f06 (diff) | |
| download | psycopg2-5fbf3ef147046548031896b49a27a21d94efae30.tar.gz | |
Merge branch 'fix-113' into devel
Diffstat (limited to 'psycopg')
| -rw-r--r-- | psycopg/connection.h | 1 | ||||
| -rw-r--r-- | psycopg/connection_int.c | 24 | ||||
| -rw-r--r-- | psycopg/green.c | 33 | ||||
| -rw-r--r-- | psycopg/python.h | 5 |
4 files changed, 39 insertions, 24 deletions
diff --git a/psycopg/connection.h b/psycopg/connection.h index 9647ffd..01cc6a4 100644 --- a/psycopg/connection.h +++ b/psycopg/connection.h @@ -141,6 +141,7 @@ HIDDEN void conn_notifies_process(connectionObject *self); RAISES_NEG HIDDEN int conn_setup(connectionObject *self, PGconn *pgconn); HIDDEN int conn_connect(connectionObject *self, long int async); HIDDEN void conn_close(connectionObject *self); +HIDDEN void conn_close_locked(connectionObject *self); RAISES_NEG HIDDEN int conn_commit(connectionObject *self); RAISES_NEG HIDDEN int conn_rollback(connectionObject *self); RAISES_NEG HIDDEN int conn_set_session(connectionObject *self, const char *isolevel, diff --git a/psycopg/connection_int.c b/psycopg/connection_int.c index 8c8fed4..a93c233 100644 --- a/psycopg/connection_int.c +++ b/psycopg/connection_int.c @@ -922,12 +922,24 @@ conn_close(connectionObject *self) return; } - /* sets this connection as closed even for other threads; also note that - we need to check the value of pgconn, because we get called even when - the connection fails! */ + /* sets this connection as closed even for other threads; */ Py_BEGIN_ALLOW_THREADS; pthread_mutex_lock(&self->lock); + conn_close_locked(self); + + pthread_mutex_unlock(&self->lock); + Py_END_ALLOW_THREADS; +} + +/* conn_close_locked - shut down the connection with the lock already taken */ + +void conn_close_locked(connectionObject *self) +{ + if (self->closed) { + return; + } + /* We used to call pq_abort_locked here, but the idea of issuing a * rollback on close/GC has been considered inappropriate. * @@ -937,9 +949,10 @@ conn_close(connectionObject *self) * transaction though: to avoid these problems the transaction should be * closed only in status CONN_STATUS_READY. */ - self->closed = 1; + /* we need to check the value of pgconn, because we get called even when + * the connection fails! */ if (self->pgconn) { PQfinish(self->pgconn); self->pgconn = NULL; @@ -947,9 +960,6 @@ conn_close(connectionObject *self) PQfreeCancel(self->cancel); self->cancel = NULL; } - - pthread_mutex_unlock(&self->lock); - Py_END_ALLOW_THREADS; } /* conn_commit - commit on a connection */ diff --git a/psycopg/green.c b/psycopg/green.c index 65578f5..3ffa810 100644 --- a/psycopg/green.c +++ b/psycopg/green.c @@ -34,7 +34,7 @@ HIDDEN PyObject *wait_callback = NULL; static PyObject *have_wait_callback(void); -static void psyco_clear_result_blocking(connectionObject *conn); +static void green_panic(connectionObject *conn); /* Register a callback function to block waiting for data. * @@ -178,7 +178,7 @@ psyco_exec_green(connectionObject *conn, const char *command) conn->async_status = ASYNC_WRITE; if (0 != psyco_wait(conn)) { - psyco_clear_result_blocking(conn); + green_panic(conn); goto end; } @@ -192,22 +192,21 @@ end: } -/* Discard the result of the currenly executed query, blocking. - * - * This function doesn't honour the wait callback: it can be used in case of - * emergency if the callback fails in order to put the connection back into a - * consistent state. - * - * If any command was issued before clearing the result, libpq would fail with - * the error "another command is already in progress". +/* There has been a communication error during query execution. It may have + * happened e.g. for a network error or an error in the callback, and we + * cannot tell the two apart. + * Trying to PQcancel or PQgetResult to put the connection back into a working + * state doesn't work nice (issue #113): the program blocks and the + * interpreter won't even respond to SIGINT. PQreset could work async, but the + * python program would have then a connection made but not configured where + * it is probably not designed to handled. So for the moment we do the kindest + * thing we can: we close the connection. A long-running program should + * already have a way to discard broken connections; a short-lived one would + * benefit of working ctrl-c. */ static void -psyco_clear_result_blocking(connectionObject *conn) +green_panic(connectionObject *conn) { - PGresult *res; - - Dprintf("psyco_clear_result_blocking"); - while (NULL != (res = PQgetResult(conn->pgconn))) { - PQclear(res); - } + Dprintf("green_panic: closing the connection"); + conn_close_locked(conn); } diff --git a/psycopg/python.h b/psycopg/python.h index 6d87fa5..f6d6be0 100644 --- a/psycopg/python.h +++ b/psycopg/python.h @@ -35,6 +35,11 @@ # error "psycopg requires Python >= 2.4" #endif +#if PY_VERSION_HEX < 0x02050000 +/* Function missing in Py 2.4 */ +#define PyErr_WarnEx(cat,msg,lvl) PyErr_Warn(cat,msg) +#endif + #if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN) typedef int Py_ssize_t; #define PY_SSIZE_T_MIN INT_MIN |
