From 2389abc295ca2e1136d357f12579fc2246a16c32 Mon Sep 17 00:00:00 2001 From: seelabs Date: Mon, 20 Apr 2015 11:32:39 -0700 Subject: [PATCH] Fix ownership of memory buffers in StatsDCollector (RIPD-756): * Ownership of buffer memory in StatsDCollector is passed to the boost::asio callback function. Before this, the memory may have been freed before async_send was finished with the memory. --- .../beast/insight/impl/StatsDCollector.cpp | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/beast/beast/insight/impl/StatsDCollector.cpp b/src/beast/beast/insight/impl/StatsDCollector.cpp index 742f60c159..7e7056c8e9 100644 --- a/src/beast/beast/insight/impl/StatsDCollector.cpp +++ b/src/beast/beast/insight/impl/StatsDCollector.cpp @@ -322,7 +322,10 @@ public: std::move (buffer)))); } - void on_send (boost::system::error_code ec, std::size_t) + // The keepAlive parameter makes sure the buffers sent to + // boost::asio::async_send do not go away until the call is finished + void on_send (std::shared_ptr> /*keepAlive*/, + boost::system::error_code ec, std::size_t) { if (ec == boost::asio::error::operation_aborted) return; @@ -354,6 +357,9 @@ public: // Send what we have void send_buffers () { + if (m_data.empty ()) + return; + // Break up the array of strings into blocks // that each fit into one UDP packet. // @@ -361,7 +367,12 @@ public: std::vector buffers; buffers.reserve (m_data.size ()); std::size_t size (0); - for (auto const& s : m_data) + + auto keepAlive = + std::make_shared>(std::move (m_data)); + m_data.clear (); + + for (auto const& s : *keepAlive) { std::size_t const length (s.size ()); assert (! s.empty ()); @@ -371,7 +382,7 @@ public: log (buffers); #endif m_socket.async_send (buffers, std::bind ( - &StatsDCollectorImp::on_send, this, + &StatsDCollectorImp::on_send, this, keepAlive, beast::asio::placeholders::error, beast::asio::placeholders::bytes_transferred)); buffers.clear (); @@ -388,11 +399,10 @@ public: log (buffers); #endif m_socket.async_send (buffers, std::bind ( - &StatsDCollectorImp::on_send, this, + &StatsDCollectorImp::on_send, this, keepAlive, beast::asio::placeholders::error, beast::asio::placeholders::bytes_transferred)); } - m_data.clear (); } void set_timer ()