From 2839bb0be1fcf4e405b30b9fb35bdd31f40b5cbd Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 1 Mar 2020 15:14:17 +0100 Subject: [PATCH] Kernel: Restore the previous thread state on SIGCONT after SIGSTOP When stopping a thread with the SIGSTOP signal, we now store the thread state in Thread::m_stop_state. That state is then restored on SIGCONT. This fixes an issue where previously-blocked threads would unblock upon resume. Now they simply resume in the Blocked state, and it's up to the regular unblocking mechanism to unblock them. Fixes #1326. --- Kernel/Thread.cpp | 14 ++++++++++---- Kernel/Thread.h | 1 + 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Kernel/Thread.cpp b/Kernel/Thread.cpp index 902934cf54e9ab..56312e7702bb32 100644 --- a/Kernel/Thread.cpp +++ b/Kernel/Thread.cpp @@ -495,13 +495,19 @@ ShouldUnblockThread Thread::dispatch_signal(u8 signal) m_pending_signals &= ~(1 << (signal - 1)); if (signal == SIGSTOP) { - m_stop_signal = SIGSTOP; - set_state(Stopped); + if (!is_stopped()) { + m_stop_signal = SIGSTOP; + m_stop_state = m_state; + set_state(State::Stopped); + } return ShouldUnblockThread::No; } - if (signal == SIGCONT && state() == Stopped) - set_state(Runnable); + if (signal == SIGCONT && is_stopped()) { + ASSERT(m_stop_state != State::Invalid); + set_state(m_stop_state); + m_stop_state = State::Invalid; + } auto handler_vaddr = action.handler_or_sigaction; if (handler_vaddr.is_null()) { diff --git a/Kernel/Thread.h b/Kernel/Thread.h index 4737056a40a6e1..f59aeee95b0239 100644 --- a/Kernel/Thread.h +++ b/Kernel/Thread.h @@ -486,6 +486,7 @@ class Thread { u32 m_priority_boost { 0 }; u8 m_stop_signal { 0 }; + State m_stop_state { Invalid }; bool m_dump_backtrace_on_finalization { false }; bool m_should_die { false };