Merge branch 'connection-closed'

NEWS for released 2.5.3 reordered.
This commit is contained in:
Daniele Varrazzo 2014-04-05 16:05:40 +01:00
commit 03b8b1e97a
7 changed files with 42 additions and 16 deletions

17
NEWS
View File

@ -15,18 +15,23 @@ What's new in psycopg 2.5.3
- Work around `pip issue #1630 <https://github.com/pypa/pip/issues/1630>`__ - Work around `pip issue #1630 <https://github.com/pypa/pip/issues/1630>`__
making installation via ``pip -e git+url`` impossible (:ticket:`#18`). making installation via ``pip -e git+url`` impossible (:ticket:`#18`).
- It is now possible to call `get_transaction_status()` on closed connections.
- Fixed unsafe access to object names causing assertion failures in
Python 3 debug builds (:ticket:`#188`).
- Mark the connection closed if found broken on `poll()` (from :ticket:`#192`
discussion)
- Fixed handling of dsn and closed attributes in connection subclasses
failing to connect (from :ticket:`#192` discussion).
- Added arbitrary but stable order to `Range` objects, thanks to - Added arbitrary but stable order to `Range` objects, thanks to
Chris Withers (:ticket:`#193`). Chris Withers (:ticket:`#193`).
- Avoid blocking async connections on connect (:ticket:`#194`). Thanks to - Avoid blocking async connections on connect (:ticket:`#194`). Thanks to
Adam Petrovich for the bug report and diagnosis. Adam Petrovich for the bug report and diagnosis.
- Fixed unsafe access to object names causing assertion failures in
Python 3 debug builds (:ticket:`#188`).
- Fixed handling of dsn and closed attributes in connection subclasses
failing to connect (from :ticket:`#192` discussion).
- Fixed overflow opening a lobject with an oid not fitting in a signed int
(:ticket:`#203`).
- Don't segfault using poorly defined cursor subclasses which forgot to call - Don't segfault using poorly defined cursor subclasses which forgot to call
the superclass init (:ticket:`#195`). 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`).
- Fixed possible segfault in named cursors creation. - Fixed possible segfault in named cursors creation.
- Fixed debug build on Windows, thanks to James Emerton. - Fixed debug build on Windows, thanks to James Emerton.

View File

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

View File

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

View File

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

View File

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

View File

@ -417,10 +417,20 @@ pq_complete_error(connectionObject *conn, PGresult **pgres, char **error)
pq_raise(conn, NULL, pgres); pq_raise(conn, NULL, pgres);
/* now *pgres is null */ /* now *pgres is null */
} }
else if (*error != NULL) { else {
PyErr_SetString(OperationalError, *error); if (*error != NULL) {
} else { PyErr_SetString(OperationalError, *error);
PyErr_SetString(OperationalError, "unknown 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;
}
} }
if (*error) { if (*error) {
@ -797,6 +807,12 @@ pq_is_busy(connectionObject *conn)
Dprintf("pq_is_busy: PQconsumeInput() failed"); Dprintf("pq_is_busy: PQconsumeInput() failed");
pthread_mutex_unlock(&(conn->lock)); pthread_mutex_unlock(&(conn->lock));
Py_BLOCK_THREADS; 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)); PyErr_SetString(OperationalError, PQerrorMessage(conn->pgconn));
return -1; return -1;
} }
@ -826,6 +842,12 @@ pq_is_busy_locked(connectionObject *conn)
if (PQconsumeInput(conn->pgconn) == 0) { if (PQconsumeInput(conn->pgconn) == 0) {
Dprintf("pq_is_busy_locked: PQconsumeInput() failed"); 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)); PyErr_SetString(OperationalError, PQerrorMessage(conn->pgconn));
return -1; return -1;
} }

View File

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