From 61639c8906d25371efb127368172330d346a6df3 Mon Sep 17 00:00:00 2001 From: "Herman S." <429230+has207@users.noreply.github.com> Date: Sun, 15 Mar 2026 21:46:01 +0900 Subject: [PATCH] [Threading/Posix] Fix issue with nested suspend When SuspendThread is called on an already-suspended thread, it would send another pthread_kill signal, which would nest signal handlers and create multiple outstanding sem_wait calls while Resume only posts once when count reaches 0. Instead we increment suspend count and skip redundant signal. --- src/xenia/base/threading_posix.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/xenia/base/threading_posix.cc b/src/xenia/base/threading_posix.cc index 7ef808b52..630e822a3 100644 --- a/src/xenia/base/threading_posix.cc +++ b/src/xenia/base/threading_posix.cc @@ -825,16 +825,26 @@ class PosixCondition final : public PosixConditionBase { // Check if we're trying to suspend ourselves bool is_current_thread = pthread_self() == thread_; + bool already_suspended = false; { std::unique_lock lock(state_mutex_); if (out_previous_suspend_count) { *out_previous_suspend_count = suspend_count_; } + already_suspended = (state_ == State::kSuspended); state_ = State::kSuspended; ++suspend_count_; } + // If already suspended, just increment the count — don't send another + // signal. A second pthread_kill while the thread is in sem_wait would + // nest signal handlers and create multiple outstanding sem_waits, but + // Resume only posts once when count reaches 0. + if (already_suspended) { + return true; + } + if (is_current_thread) { // Self-suspension: Instead of sending a signal, directly call // WaitSuspended. This avoids the signal handler complexity for the