Merge branch 'connection-closed' into maint_2_4

This commit is contained in:
Daniele Varrazzo 2014-04-07 18:30:33 +01:00
commit ed968dd913
7 changed files with 36 additions and 10 deletions

5
NEWS
View File

@ -3,6 +3,8 @@ What's new in psycopg 2.4.7
- Work around `pip issue #1630 <https://github.com/pypa/pip/issues/1630>`__
making installation via ``pip -e git+url`` impossible (:ticket:`#18`).
- It is now possible to call `get_transaction_status()` on closed
connections.
- Properly cleanup memory of broken connections (ticket #142).
- Fixed build on Solaris 10 and 11 where the round() function is already
declared (:ticket:`#146`).
@ -20,8 +22,11 @@ What's new in psycopg 2.4.7
failing to connect (from :ticket:`#192` discussion).
- Don't segfault using poorly defined cursor subclasses which forgot to call
the superclass init (:ticket:`#195`).
- Mark the connection closed when a Socket connection is broken, as it
happens for TCP connections instead (:ticket:`#196`).
- Fixed overflow opening a lobject with an oid not fitting in a signed int
(:ticket:`#203`).
- Mark the connection closed if found broken on `poll()`.
- Fixed possible segfault in named cursors creation.
- Fixed debug build on Windows, thanks to James Emerton.

View File

@ -283,8 +283,8 @@ The ``connection`` class
.. attribute:: closed
Read-only attribute reporting whether the database connection is open
(0) or closed (1).
Read-only integer attribute: 0 if the connection is open, nonzero if
it is closed or broken.
.. method:: cancel

View File

@ -647,8 +647,6 @@ psyco_conn_set_client_encoding(connectionObject *self, PyObject *args)
static PyObject *
psyco_conn_get_transaction_status(connectionObject *self, PyObject *args)
{
EXC_IF_CONN_CLOSED(self);
return PyInt_FromLong((long)PQtransactionStatus(self->pgconn));
}

View File

@ -253,7 +253,7 @@ lobject_close_locked(lobjectObject *self, char **error)
return 0;
break;
default:
PyErr_SetString(OperationalError, "the connection is broken");
*error = strdup("the connection is broken");
return -1;
break;
}

View File

@ -359,7 +359,7 @@ lobject_dealloc(PyObject* obj)
{
lobjectObject *self = (lobjectObject *)obj;
if (self->conn) { /* if not, init failed */
if (self->conn && self->fd != -1) {
if (lobject_close(self) < 0)
PyErr_Print();
Py_XDECREF((PyObject*)self->conn);

View File

@ -388,13 +388,23 @@ pq_complete_error(connectionObject *conn, PGresult **pgres, char **error)
{
Dprintf("pq_complete_error: pgconn = %p, pgres = %p, error = %s",
conn->pgconn, *pgres, *error ? *error : "(null)");
if (*pgres != NULL)
if (*pgres != NULL) {
pq_raise(conn, NULL, *pgres);
else if (*error != NULL) {
} else {
if (*error != NULL) {
PyErr_SetString(OperationalError, *error);
} else {
PyErr_SetString(OperationalError, "unknown error");
}
/* Trivia: with a broken socket connection PQexec returns NULL, so we
* end up here. With a TCP connection we get a pgres with an error
* instead, and the connection gets closed in the pq_raise call above
* (see ticket #196)
*/
if (CONNECTION_BAD == PQstatus(conn->pgconn)) {
conn->closed = 2;
}
}
IFCLEARPGRES(*pgres);
if (*error) {
free(*error);
@ -764,6 +774,12 @@ pq_is_busy(connectionObject *conn)
Dprintf("pq_is_busy: PQconsumeInput() failed");
pthread_mutex_unlock(&(conn->lock));
Py_BLOCK_THREADS;
/* if the libpq says pgconn is lost, close the py conn */
if (CONNECTION_BAD == PQstatus(conn->pgconn)) {
conn->closed = 2;
}
PyErr_SetString(OperationalError, PQerrorMessage(conn->pgconn));
return -1;
}
@ -793,6 +809,12 @@ pq_is_busy_locked(connectionObject *conn)
if (PQconsumeInput(conn->pgconn) == 0) {
Dprintf("pq_is_busy_locked: PQconsumeInput() failed");
/* if the libpq says pgconn is lost, close the py conn */
if (CONNECTION_BAD == PQstatus(conn->pgconn)) {
conn->closed = 2;
}
PyErr_SetString(OperationalError, PQerrorMessage(conn->pgconn));
return -1;
}

View File

@ -138,6 +138,7 @@ class LargeObjectTests(LargeObjectMixin, unittest.TestCase):
self.assertRaises(psycopg2.OperationalError,
self.conn.lobject, 0, "w", lo.oid)
self.assert_(not self.conn.closed)
def test_import(self):
self.tmpdir = tempfile.mkdtemp()