summaryrefslogtreecommitdiff
path: root/psycopg
diff options
context:
space:
mode:
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>2012-10-11 22:25:59 +0100
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>2012-10-11 22:26:51 +0100
commit5fbf3ef147046548031896b49a27a21d94efae30 (patch)
tree00710eb709a08041f80a326b909d7136347e1626 /psycopg
parentee763e0f47802232000293b3e4e33d87f7d19720 (diff)
parentb61a2a34c40e9b6e8774178e553a2e81eb889f06 (diff)
downloadpsycopg2-5fbf3ef147046548031896b49a27a21d94efae30.tar.gz
Merge branch 'fix-113' into devel
Diffstat (limited to 'psycopg')
-rw-r--r--psycopg/connection.h1
-rw-r--r--psycopg/connection_int.c24
-rw-r--r--psycopg/green.c33
-rw-r--r--psycopg/python.h5
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