From ebf5fd6fd3eb48bfb1015ad4f6a2aa57d4eb5668 Mon Sep 17 00:00:00 2001 From: Gordon Sim Date: Wed, 17 Jun 2009 17:13:13 +0000 Subject: Ensure that the ConnectionTimeoutTask does not block other tasks (e.g. ConnectionHeartbeatTask) by having the timeout changed after it has been submitted. git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@785733 13f79535-47bb-0310-9956-ffa450edef68 --- cpp/src/qpid/broker/Connection.cpp | 54 +++++++++++++++++++++++--------------- cpp/src/qpid/broker/Connection.h | 3 ++- 2 files changed, 35 insertions(+), 22 deletions(-) (limited to 'cpp/src') diff --git a/cpp/src/qpid/broker/Connection.cpp b/cpp/src/qpid/broker/Connection.cpp index a57b59ae2c..fb087181a3 100644 --- a/cpp/src/qpid/broker/Connection.cpp +++ b/cpp/src/qpid/broker/Connection.cpp @@ -48,6 +48,38 @@ namespace _qmf = qmf::org::apache::qpid::broker; namespace qpid { namespace broker { +struct ConnectionTimeoutTask : public TimerTask { + Timer& timer; + Connection& connection; + AbsTime expires; + + ConnectionTimeoutTask(uint16_t hb, Timer& t, Connection& c) : + TimerTask(Duration(hb*2*TIME_SEC)), + timer(t), + connection(c), + expires(AbsTime::now(), duration) + {} + + void touch() + { + expires = AbsTime(AbsTime::now(), duration); + } + + void fire() { + // This is the best we can currently do to avoid a destruction/fire race + if (isCancelled()) return; + if (expires < AbsTime::now()) { + // If we get here then we've not received any traffic in the timeout period + // Schedule closing the connection for the io thread + QPID_LOG(error, "Connection timed out: closing"); + connection.abort(); + } else { + reset(); + timer.add(this); + } + } +}; + Connection::Connection(ConnectionOutputHandler* out_, Broker& broker_, const std::string& mgmtId_, bool isLink_, uint64_t objectId) : ConnectionState(out_, broker_), adapter(*this, isLink_), @@ -325,26 +357,6 @@ struct ConnectionHeartbeatTask : public TimerTask { } }; -struct ConnectionTimeoutTask : public TimerTask { - Timer& timer; - Connection& connection; - ConnectionTimeoutTask(uint16_t hb, Timer& t, Connection& c) : - TimerTask(Duration(hb*2*TIME_SEC)), - timer(t), - connection(c) - {} - - void fire() { - // This is the best we can currently do to avoid a destruction/fire race - if (!isCancelled()) { - // If we get here then we've not received any traffic in the timeout period - // Schedule closing the connection for the io thread - QPID_LOG(error, "Connection timed out: closing"); - connection.abort(); - } - } -}; - void Connection::abort() { out.abort(); @@ -364,7 +376,7 @@ void Connection::setHeartbeatInterval(uint16_t heartbeat) void Connection::restartTimeout() { if (timeoutTimer) - timeoutTimer->reset(); + timeoutTimer->touch(); } }} diff --git a/cpp/src/qpid/broker/Connection.h b/cpp/src/qpid/broker/Connection.h index db18c48d82..540f64a8ed 100644 --- a/cpp/src/qpid/broker/Connection.h +++ b/cpp/src/qpid/broker/Connection.h @@ -60,6 +60,7 @@ namespace broker { class LinkRegistry; class SecureConnection; +struct ConnectionTimeoutTask; class Connection : public sys::ConnectionInputHandler, public ConnectionState, @@ -153,7 +154,7 @@ class Connection : public sys::ConnectionInputHandler, management::ManagementAgent* agent; Timer& timer; boost::intrusive_ptr heartbeatTimer; - boost::intrusive_ptr timeoutTimer; + boost::intrusive_ptr timeoutTimer; ErrorListener* errorListener; bool shadow; -- cgit v1.2.1