From c95ad020fb529d47f9c3106a53553bec955c1586 Mon Sep 17 00:00:00 2001 From: lizzie Date: Fri, 11 Sep 2026 15:29:52 +0200 Subject: [PATCH] [gpu] Fix infinite hangup/freezes at shutdown/reset (#4395) Thread may be destroyed at dtor(), but it hasn't fully shut down, so before notify shutdown, request immediate stop (effective immediately). Like the issue was that the thread didn't want to stop running, thus it would hang, it would also reference objects which were being destroyed without waiting for them to actually be destroyed So it would reference invalid data This PR tells the thread: "hey, STOP now, and DESTROY yourself" So all of that should be avoided Signed-off-by: lizzie - [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions). - [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md) - [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability. ------------------- Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4395 Reviewed-by: Maufeat Reviewed-by: MaranBr --- src/video_core/gpu.cpp | 9 +++++---- src/video_core/gpu_thread.cpp | 7 +++++++ src/video_core/gpu_thread.h | 2 ++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index a2e87b260a..9901cf4262 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -55,8 +55,8 @@ constexpr u64 GpuClockMultiplier(Settings::GpuClock clock) { struct GPU::Impl { explicit Impl(Core::System& system_, bool is_async_, bool use_nvdec_) - : gpu_thread{system_} - , system{system_} + : system{system_} + , gpu_thread{system_} , use_nvdec{use_nvdec_} , shader_notify() , is_async{is_async_} @@ -182,6 +182,7 @@ struct GPU::Impl { } void NotifyShutdown() { + gpu_thread.NotifyShutdown(); std::unique_lock lk{sync_mutex}; shutting_down.store(true, std::memory_order::relaxed); sync_cv.notify_all(); @@ -301,12 +302,12 @@ struct GPU::Impl { return out; } + Core::System& system; + // Destruction of thread must be done before all (non trivial) // previous members has been destroyed VideoCommon::GPUThread::ThreadManager gpu_thread; - Core::System& system; - std::unique_ptr renderer; const bool use_nvdec; diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index 2acf9ac458..a01375e7be 100644 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp @@ -114,4 +114,11 @@ u64 ThreadManager::PushCommand(CommandData&& command_data, bool block, bool is_a return fence; } +void ThreadManager::NotifyShutdown() { + if (thread.joinable()) { + thread.request_stop(); + thread.join(); + } +} + } // namespace VideoCommon::GPUThread diff --git a/src/video_core/gpu_thread.h b/src/video_core/gpu_thread.h index 4c3fadce15..631a680db4 100644 --- a/src/video_core/gpu_thread.h +++ b/src/video_core/gpu_thread.h @@ -125,6 +125,8 @@ public: void TickGPU(bool is_async); + void NotifyShutdown(); + private: /// Pushes a command to be executed by the GPU thread u64 PushCommand(CommandData&& command_data, bool block, bool is_async);