From 6d8b2a4e9efa19e93d5cc3732ab7d00baf7566f1 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 7 Dec 2015 14:15:26 +0000 Subject: Improve connection failure detection --- libpqpp/connection.cpp | 4 +++- libpqpp/unittests/testpq.cpp | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) 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 +#include #include 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(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(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 ) -- cgit v1.2.3