From 29d644e9d3fbd3fa2db224825370ca8323291fe7 Mon Sep 17 00:00:00 2001 From: Tom Ritchford Date: Mon, 20 Apr 2015 15:37:39 -0400 Subject: [PATCH] Fix WebSockets treatment of ping timer: This solves a problem that caused a hang on shutdown related to the lifetime of the ping timer completion handlers used in WebSockets. * Turn the ping timer back on * Use std::weak_ptr for WebSockets timer callbacks. * Disable WebSocket pings if frequency in the .cfg is non-positive. --- src/ripple/websocket/Connection.h | 1 - src/ripple/websocket/Handler.h | 1 + src/ripple/websocket/WebSocket02.cpp | 21 +++++++++++---------- src/ripple/websocket/WebSocket04.cpp | 14 +++++++++----- 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/ripple/websocket/Connection.h b/src/ripple/websocket/Connection.h index 0346ace01..390bd7b78 100644 --- a/src/ripple/websocket/Connection.h +++ b/src/ripple/websocket/Connection.h @@ -139,7 +139,6 @@ ConnectionImpl ::ConnectionImpl ( , m_handler (handler) , m_connection (cpConnection) { - setPingTimer (); } template diff --git a/src/ripple/websocket/Handler.h b/src/ripple/websocket/Handler.h index d18cfb37b..687a73976 100644 --- a/src/ripple/websocket/Handler.h +++ b/src/ripple/websocket/Handler.h @@ -208,6 +208,7 @@ public: cpClient, makeBeastEndpoint (remoteEndpoint), WebSocket::getStrand (*cpClient).get_io_service ()); + connection->setPingTimer (); auto result = mMap.emplace (cpClient, std::move (connection)); assert (result.second); diff --git a/src/ripple/websocket/WebSocket02.cpp b/src/ripple/websocket/WebSocket02.cpp index da9c20b0b..b194a467b 100644 --- a/src/ripple/websocket/WebSocket02.cpp +++ b/src/ripple/websocket/WebSocket02.cpp @@ -20,6 +20,7 @@ #include #include #include +#include // This file contains websocket::WebSocket02 implementations for the WebSocket // generic functions as well as methods on Server and ConnectionImpl. @@ -72,22 +73,22 @@ boost::asio::io_service::strand& WebSocket02::getStrand (Connection& con) template <> void ConnectionImpl ::setPingTimer () { -#if 0 + auto freq = getConfig ().WEBSOCKET_PING_FREQ; + if (freq <= 0) + return; connection_ptr ptr = m_connection.lock (); if (ptr) { - this->m_pingTimer.expires_from_now (boost::posix_time::seconds - (getConfig ().WEBSOCKET_PING_FREQ)); + this->m_pingTimer.expires_from_now (boost::posix_time::seconds (freq)); - auto pt = [this] (boost::system::error_code const& e) - { - this->pingTimer (e); - }; - - this->m_pingTimer.async_wait (ptr->get_strand ().wrap (pt)); + this->m_pingTimer.async_wait ( + ptr->get_strand ().wrap ( + std::bind ( + beast::weak_fn (&ConnectionImpl ::pingTimer, + shared_from_this()), + beast::asio::placeholders::error))); } -#endif } template <> diff --git a/src/ripple/websocket/WebSocket04.cpp b/src/ripple/websocket/WebSocket04.cpp index cce1b4b2f..287f5a9f5 100644 --- a/src/ripple/websocket/WebSocket04.cpp +++ b/src/ripple/websocket/WebSocket04.cpp @@ -22,6 +22,7 @@ #include #include +#include namespace ripple { namespace websocket { @@ -114,16 +115,19 @@ EndpointPtr04 WebSocket04::makeEndpoint (HandlerPtr&& handler) template <> void ConnectionImpl ::setPingTimer () { + auto freq = getConfig ().WEBSOCKET_PING_FREQ; + if (freq <= 0) + return; if (auto con = m_connection.lock ()) { - auto t = boost::posix_time::seconds (getConfig ().WEBSOCKET_PING_FREQ); + auto t = boost::posix_time::seconds (freq); auto ms = t.total_milliseconds(); con->set_timer ( ms, - [this] (WebSocket04::ErrorCode const& e) - { - this->pingTimer (e); - }); + std::bind ( + beast::weak_fn (&ConnectionImpl ::pingTimer, + shared_from_this()), + beast::asio::placeholders::error)); } }