Repository: mesos
Updated Branches:
  refs/heads/master 3ae937fb1 -> 1ebb62b7b


Fixed deadlock in libev.

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


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

Branch: refs/heads/master
Commit: 1ebb62b7b5ad04d1e9c9bdd9c363110dec8ca7c9
Parents: 3ae937f
Author: Joris Van Remoortere <[email protected]>
Authored: Mon Aug 17 16:17:49 2015 -0700
Committer: Vinod Kone <[email protected]>
Committed: Mon Aug 17 16:18:37 2015 -0700

----------------------------------------------------------------------
 3rdparty/libprocess/src/libev.cpp | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/1ebb62b7/3rdparty/libprocess/src/libev.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/libev.cpp 
b/3rdparty/libprocess/src/libev.cpp
index aca10a1..97a2694 100644
--- a/3rdparty/libprocess/src/libev.cpp
+++ b/3rdparty/libprocess/src/libev.cpp
@@ -45,6 +45,7 @@ THREAD_LOCAL bool* _in_event_loop_ = NULL;
 
 void handle_async(struct ev_loop* loop, ev_async* _, int revents)
 {
+  std::queue<lambda::function<void(void)>> run_functions;
   synchronized (watchers_mutex) {
     // Start all the new I/O watchers.
     while (!watchers->empty()) {
@@ -53,10 +54,22 @@ void handle_async(struct ev_loop* loop, ev_async* _, int 
revents)
       ev_io_start(loop, watcher);
     }
 
-    while (!functions->empty()) {
-      (functions->front())();
-      functions->pop();
-    }
+    // Swap the functions into a temporary queue so that we can invoke
+    // them outside of the mutex.
+    std::swap(run_functions, *functions);
+  }
+
+  // Running the functions outside of the mutex reduces locking
+  // contention as these are arbitrary functions that can take a long
+  // time to execute. Doing this also avoids a deadlock scenario where
+  // (A) mutexes are acquired before calling `run_in_event_loop`,
+  // followed by locking (B) `watchers_mutex`. If we executed the
+  // functions inside the mutex, then the locking order violation
+  // would be this function acquiring the (B) `watchers_mutex`
+  // followed by the arbitrary function acquiring the (A) mutexes.
+  while (!run_functions.empty()) {
+    (run_functions.front())();
+    run_functions.pop();
   }
 }
 

Reply via email to