summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2015-12-07 14:15:26 +0000
committerDan Goodliffe <dan@randomdan.homeip.net>2015-12-07 14:15:26 +0000
commit6d8b2a4e9efa19e93d5cc3732ab7d00baf7566f1 (patch)
tree2bf6a1310271eddcd5127c34739c4ea6465b2150
parentFix leak of error message in exception (diff)
downloadlibdbpp-postgresql-6d8b2a4e9efa19e93d5cc3732ab7d00baf7566f1.tar.bz2
libdbpp-postgresql-6d8b2a4e9efa19e93d5cc3732ab7d00baf7566f1.tar.xz
libdbpp-postgresql-6d8b2a4e9efa19e93d5cc3732ab7d00baf7566f1.zip
Improve connection failure detection
-rw-r--r--libpqpp/connection.cpp4
-rw-r--r--libpqpp/unittests/testpq.cpp38
2 files changed, 41 insertions, 1 deletions
diff --git a/libpqpp/connection.cpp b/libpqpp/connection.cpp
index 57531e3..de3f189 100644
--- a/libpqpp/connection.cpp
+++ b/libpqpp/connection.cpp
@@ -3,6 +3,7 @@
#include "selectcommand.h"
#include "modifycommand.h"
#include <unistd.h>
+#include <poll.h>
#include <boost/assert.hpp>
NAMEDFACTORY("postgresql", PQ::Connection, DB::ConnectionFactory);
@@ -108,7 +109,8 @@ PQ::Connection::bulkUpdateStyle() const
void
PQ::Connection::ping() const
{
- if (PQstatus(conn) != CONNECTION_OK) {
+ struct pollfd fd { PQsocket(conn), POLLRDHUP | POLLERR | POLLHUP | POLLNVAL, 0 };
+ if (PQstatus(conn) != CONNECTION_OK || poll(&fd, 1, 1)) {
if (inTx()) {
throw ConnectionError(conn);
}
diff --git a/libpqpp/unittests/testpq.cpp b/libpqpp/unittests/testpq.cpp
index 002b18c..3f55c63 100644
--- a/libpqpp/unittests/testpq.cpp
+++ b/libpqpp/unittests/testpq.cpp
@@ -169,6 +169,44 @@ BOOST_AUTO_TEST_CASE( insertId )
delete ro;
}
+BOOST_AUTO_TEST_CASE( reconnect )
+{
+ auto ro = DB::MockDatabase::openConnectionTo("pqmock");
+ auto rok = DB::MockDatabase::openConnectionTo("pqmock");
+ auto pqconn = dynamic_cast<PQ::Connection *>(ro);
+ int pid1 = PQbackendPID(pqconn->conn);
+ BOOST_REQUIRE(pid1);
+ ro->ping();
+ auto kil = rok->newModifyCommand("SELECT pg_terminate_backend(?)");
+ kil->bindParamI(0, pid1);
+ kil->execute();
+ delete kil;
+ ro->ping();
+ int pid2 = PQbackendPID(pqconn->conn);
+ BOOST_REQUIRE(pid2);
+ BOOST_REQUIRE(pid1 != pid2);
+ delete ro;
+ delete rok;
+}
+
+BOOST_AUTO_TEST_CASE( reconnectInTx )
+{
+ auto ro = DB::MockDatabase::openConnectionTo("pqmock");
+ auto rok = DB::MockDatabase::openConnectionTo("pqmock");
+ auto pqconn = dynamic_cast<PQ::Connection *>(ro);
+ int pid1 = PQbackendPID(pqconn->conn);
+ BOOST_REQUIRE(pid1);
+ ro->ping();
+ ro->beginTx();
+ auto kil = rok->newModifyCommand("SELECT pg_terminate_backend(?)");
+ kil->bindParamI(0, pid1);
+ kil->execute();
+ delete kil;
+ BOOST_REQUIRE_THROW(ro->ping(), PQ::ConnectionError);
+ delete ro;
+ delete rok;
+}
+
BOOST_AUTO_TEST_SUITE_END();
BOOST_AUTO_TEST_CASE( connfail )