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(); } }
