You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mesos.apache.org by jo...@apache.org on 2016/09/28 20:55:13 UTC

[3/3] mesos git commit: Added synchronization in link logic to prevent relinking races.

Added synchronization in link logic to prevent relinking races.

There is a general pattern in the `SocketManager` in which most methods
will grab the mutex and then check if the socket to manage exists in
the `SocketManager`s mapping.  If the socket does not exist, the
`SocketManager` silently returns.

This adds similar logic inside two critical sections of the `link`
codepath.  If there are multiple calls to `link` in-flight at once,
this prevents sockets from being leaked into unmanaged callback loops.

Review: https://reviews.apache.org/r/52181/


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/3b27c92f
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/3b27c92f
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/3b27c92f

Branch: refs/heads/master
Commit: 3b27c92f9b31d9b40c86f368ebd30c97d4fb69e8
Parents: 79c72d7
Author: Joseph Wu <jo...@mesosphere.io>
Authored: Wed Sep 28 12:33:47 2016 -0700
Committer: Joseph Wu <jo...@apache.org>
Committed: Wed Sep 28 12:33:47 2016 -0700

----------------------------------------------------------------------
 3rdparty/libprocess/src/process.cpp | 43 ++++++++++++++++++++++++--------
 1 file changed, 32 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/3b27c92f/3rdparty/libprocess/src/process.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/process.cpp b/3rdparty/libprocess/src/process.cpp
index c03fec6..f1d746c 100644
--- a/3rdparty/libprocess/src/process.cpp
+++ b/3rdparty/libprocess/src/process.cpp
@@ -1505,16 +1505,26 @@ void SocketManager::link_connect(
     return;
   }
 
-  size_t size = 80 * 1024;
-  char* data = new char[size];
+  synchronized (mutex) {
+    // It is possible that a prior call to `link()` with `RECONNECT`
+    // semantics has swapped out this socket before we finished
+    // connecting. In this case, we simply stop here and allow the
+    // latest created socket to complete the link.
+    if (sockets.count(socket) <= 0) {
+      return;
+    }
 
-  socket.recv(data, size)
-    .onAny(lambda::bind(
-        &internal::ignore_recv_data,
-        lambda::_1,
-        socket,
-        data,
-        size));
+    size_t size = 80 * 1024;
+    char* data = new char[size];
+
+    socket.recv(data, size)
+      .onAny(lambda::bind(
+          &internal::ignore_recv_data,
+          lambda::_1,
+          socket,
+          data,
+          size));
+  }
 
   // In order to avoid a race condition where internal::send() is
   // called after SocketManager::link() but before the socket is
@@ -1611,11 +1621,22 @@ void SocketManager::link(
 
         // Update all the data structures that are mapped to the old
         // socket. They will now point to the new socket we are about
-        // to try to connect. The old socket should no longer have any
-        // references after the swap and should be closed.
+        // to try to connect.
         Socket existing(sockets.at(persists.at(to.address)));
         swap_implementing_socket(existing, socket.get());
 
+        // The `existing` socket could be a perfectly functional socket.
+        // In this case, the socket may be referenced in the callback
+        // loop of `internal::ignore_recv_data`. We shutdown the socket
+        // in order to interrupt this callback loop and thereby release
+        // the final socket reference. This will not result in an
+        // `ExitedEvent` because we have already removed the `existing`
+        // socket from the mapping of linkees and linkers.
+        Try<Nothing> shutdown = existing.shutdown();
+        if (shutdown.isError()) {
+          VLOG(1) << "Failed to shutdown old link: " << shutdown.error();
+        }
+
         connect = true;
       }
     }