Ver Fonte

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.
Andreas Kling há 5 anos atrás
pai
commit
2839bb0be1
2 ficheiros alterados com 11 adições e 4 exclusões
  1. 10 4
      Kernel/Thread.cpp
  2. 1 0
      Kernel/Thread.h

+ 10 - 4
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()) {

+ 1 - 0
Kernel/Thread.h

@@ -486,6 +486,7 @@ private:
     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 };