From 09ab139407b6ce9b3bfbeaeafbd7b51faae1863b Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Thu, 15 Aug 2024 11:55:07 +0200 Subject: [PATCH] android: deadlock when Emulator::checkStatus is called concurrently If checkStatus(wait = true) is called, any other thread will be blocked even when calling with wait = false since the mutex is locked. This happens on Android when JNIdc.rendinitNative(null) is called by the app main thread. Use a shared_future instead and unlock the mutex before waiting. --- core/emulator.cpp | 13 +++++++++---- core/emulator.h | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/core/emulator.cpp b/core/emulator.cpp index e39fc19d4..1ed9a22dc 100644 --- a/core/emulator.cpp +++ b/core/emulator.cpp @@ -908,15 +908,20 @@ void Emulator::start() bool Emulator::checkStatus(bool wait) { try { - const std::lock_guard lock(mutex); + std::unique_lock lock(mutex); if (threadResult.valid()) { - if (!wait) - { - auto result = threadResult.wait_for(std::chrono::seconds(0)); + lock.unlock(); + auto localResult = threadResult; + if (wait) { + localResult.wait(); + } + else { + auto result = localResult.wait_for(std::chrono::seconds(0)); if (result == std::future_status::timeout) return true; } + lock.lock(); threadResult.get(); } return false; diff --git a/core/emulator.h b/core/emulator.h index 6802b00e8..eb2a698be 100644 --- a/core/emulator.h +++ b/core/emulator.h @@ -179,7 +179,7 @@ private: Terminated, }; State state = Uninitialized; - std::future threadResult; + std::shared_future threadResult; bool resetRequested = false; bool singleStep = false; u64 startTime = 0;