Browse Source

[2946] pass shared_ptr, not a reference to deadline pointer.

I suspect the previous version could cause the same type of use-after-free
bug, although I couldn't come up with an effective test scenario.
JINMEI Tatuya 12 years ago
parent
commit
935c7cc403
1 changed files with 16 additions and 13 deletions
  1. 16 13
      src/lib/asiodns/tcp_server.cc

+ 16 - 13
src/lib/asiodns/tcp_server.cc

@@ -77,18 +77,18 @@ TCPServer::TCPServer(io_service& io_service, int fd, int af,
 }
 
 namespace {
-    // Called by the timeout_ deadline timer if the client takes too long.
-    // If not aborted, cancels the given socket
-    // (in which case TCPServer::operator() will be called to continue,
-    // with an 'aborted' error code
-    void do_timeout(asio::ip::tcp::socket& socket,
-                    const asio::error_code& error)
-    {
-        if (error != asio::error::operation_aborted) {
-            socket.cancel();
-        }
+// Called by the timeout_ deadline timer if the client takes too long.
+// If not aborted, cancels the given socket
+// (in which case TCPServer::operator() will be called to continue,
+// with an 'aborted' error code.)
+void doTimeOut(boost::shared_ptr<asio::ip::tcp::socket> socket,
+               const asio::error_code& error)
+{
+    if (error != asio::error::operation_aborted) {
+        socket->cancel();
     }
 }
+}
 
 void
 TCPServer::operator()(asio::error_code ec, size_t length) {
@@ -149,13 +149,16 @@ TCPServer::operator()(asio::error_code ec, size_t length) {
         /// asynchronous read call.
         data_.reset(new char[MAX_LENGTH]);
 
-        /// Start a timer to drop the connection if it is idle
+        /// Start a timer to drop the connection if it is idle.  note that
+        // we pass a shared_ptr of the socket object so that it won't be
+        // destroyed at least until the timeout callback (including abort)
+        // is called.
         if (*tcp_recv_timeout_ > 0) {
             timeout_.reset(new asio::deadline_timer(io_)); // shouldn't throw
             timeout_->expires_from_now( // consider any exception fatal.
                 boost::posix_time::milliseconds(*tcp_recv_timeout_));
-            timeout_->async_wait(boost::bind(&do_timeout, boost::ref(*socket_),
-                                 asio::placeholders::error));
+            timeout_->async_wait(boost::bind(&doTimeOut, socket_,
+                                             asio::placeholders::error));
         }
 
         /// Read the message, in two parts.  First, the message length: