[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.
This commit is contained in:
Herman S.
2026-03-15 21:46:01 +09:00
parent 7cd9aa21b3
commit 61639c8906

View File

@@ -825,16 +825,26 @@ class PosixCondition<Thread> final : public PosixConditionBase {
// Check if we're trying to suspend ourselves // Check if we're trying to suspend ourselves
bool is_current_thread = pthread_self() == thread_; bool is_current_thread = pthread_self() == thread_;
bool already_suspended = false;
{ {
std::unique_lock lock(state_mutex_); std::unique_lock lock(state_mutex_);
if (out_previous_suspend_count) { if (out_previous_suspend_count) {
*out_previous_suspend_count = suspend_count_; *out_previous_suspend_count = suspend_count_;
} }
already_suspended = (state_ == State::kSuspended);
state_ = State::kSuspended; state_ = State::kSuspended;
++suspend_count_; ++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) { if (is_current_thread) {
// Self-suspension: Instead of sending a signal, directly call // Self-suspension: Instead of sending a signal, directly call
// WaitSuspended. This avoids the signal handler complexity for the // WaitSuspended. This avoids the signal handler complexity for the