diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index ff50cb5d04..0add453553 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -810,10 +810,23 @@ ShouldUnblockProcess Process::dispatch_signal(byte signal) // Mark this signal as handled. m_pending_signals &= ~(1 << signal); + if (signal == SIGSTOP) { + set_state(Stopped); + return ShouldUnblockProcess::No; + } + if (signal == SIGCONT && state() == Stopped) { + set_state(Runnable); + return ShouldUnblockProcess::Yes; + } + auto handler_laddr = action.handler_or_sigaction; if (handler_laddr.is_null()) { - // FIXME: Is termination really always the appropriate action? - terminate_due_to_signal(signal); + if (signal == SIGSTOP) { + set_state(Stopped); + } else { + // FIXME: Is termination really always the appropriate action? + terminate_due_to_signal(signal); + } return ShouldUnblockProcess::No; } diff --git a/Kernel/Process.h b/Kernel/Process.h index 182ca1ce7d..47769e9e2d 100644 --- a/Kernel/Process.h +++ b/Kernel/Process.h @@ -65,6 +65,7 @@ public: Skip0SchedulerPasses, Dying, Dead, + Stopped, BeingInspected, BlockedLurking, BlockedSleep, @@ -89,7 +90,7 @@ public: bool is_ring0() const { return m_ring == Ring0; } bool is_ring3() const { return m_ring == Ring3; } - + bool is_stopped() const { return m_state == Stopped; } bool is_blocked() const { return m_state == BlockedSleep || m_state == BlockedWait || m_state == BlockedRead || m_state == BlockedWrite || m_state == BlockedSignal || m_state == BlockedSelect; @@ -444,6 +445,7 @@ static inline const char* to_string(Process::State state) case Process::Running: return "Running"; case Process::Dying: return "Dying"; case Process::Dead: return "Dead"; + case Process::Stopped: return "Stopped"; case Process::Skip1SchedulerPass: return "Skip1"; case Process::Skip0SchedulerPasses: return "Skip0"; case Process::BlockedSleep: return "Sleep"; diff --git a/Kernel/Scheduler.cpp b/Kernel/Scheduler.cpp index 07e199cd8f..8b89f4e4fb 100644 --- a/Kernel/Scheduler.cpp +++ b/Kernel/Scheduler.cpp @@ -168,7 +168,7 @@ bool Scheduler::pick_next() // FIXME: Maybe we could check when returning from a syscall if there's a pending // signal and dispatch it then and there? Would that be doable without the // syscall effectively being "interrupted" despite having completed? - if (process.in_kernel() && !process.is_blocked()) + if (process.in_kernel() && !process.is_blocked() && !process.is_stopped()) return true; // NOTE: dispatch_one_pending_signal() may unblock the process. bool was_blocked = process.is_blocked();