From f3f2bfdc24f4190880323ea4927c694a7a8b673d Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Sat, 1 May 2021 21:01:47 +0200 Subject: [PATCH] Fix deadlock caused by do_mutual_recursion_on_off_thread Apparently the destructor for C++17/20 conditional initializers are only run after the else branch, so this would keep the mutex locked while executing `do_call()`. --- src/wine-host/bridges/vst3.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/wine-host/bridges/vst3.h b/src/wine-host/bridges/vst3.h index 5c6139ff..edebe9d5 100644 --- a/src/wine-host/bridges/vst3.h +++ b/src/wine-host/bridges/vst3.h @@ -347,8 +347,8 @@ class Vst3Bridge : public HostBridge { // `mutual_recursion_contexts` will be blocked until the deeper calls // are finished. { - if (std::lock_guard lock(mutual_recursion_contexts_mutex); - !mutual_recursion_contexts.empty()) { + std::lock_guard lock(mutual_recursion_contexts_mutex); + if (!mutual_recursion_contexts.empty()) { boost::asio::dispatch(*mutual_recursion_contexts.back(), std::move(do_call)); } else { @@ -370,11 +370,15 @@ class Vst3Bridge : public HostBridge { std::packaged_task do_call(std::move(f)); std::future do_call_response = do_call.get_future(); - if (std::lock_guard lock(mutual_recursion_contexts_mutex); - !mutual_recursion_contexts.empty()) { + std::unique_lock lock(mutual_recursion_contexts_mutex); + if (!mutual_recursion_contexts.empty()) { boost::asio::dispatch(*mutual_recursion_contexts.back(), std::move(do_call)); } else { + // Unlike the other branches in the `do_mutual_recursion_*` + // functions, this one will block + lock.unlock(); + do_call(); }