From 3c3a1726df847aff9db73862040d9f7a3b9fc907 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Sat, 19 Jun 2021 11:27:20 +0200 Subject: [PATCH] Kernel: Make sure threads which don't do any syscalls are terminated Steps to reproduce: $ cat loop.c int main() { for (;;); } $ gcc -o loop loop.c $ ./loop Terminating this process wasn't previously possible because we only checked whether the thread should be terminated on syscall exit. --- Kernel/Scheduler.cpp | 7 +++++++ Kernel/Syscall.cpp | 9 +++++++++ Kernel/Thread.h | 4 ++++ 3 files changed, 20 insertions(+) diff --git a/Kernel/Scheduler.cpp b/Kernel/Scheduler.cpp index 98f6000d7a..c630ae0ad4 100644 --- a/Kernel/Scheduler.cpp +++ b/Kernel/Scheduler.cpp @@ -192,6 +192,13 @@ bool Scheduler::pick_next() ScopedSpinLock lock(g_scheduler_lock); + auto current_thread = Thread::current(); + if (current_thread->should_die() && current_thread->may_die_immediately()) { + // Ordinarily the thread would die on syscall exit, however if the thread + // doesn't perform any syscalls we still need to mark it for termination here. + current_thread->set_state(Thread::Dying); + } + if constexpr (SCHEDULER_RUNNABLE_DEBUG) { dump_thread_list(); } diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp index e9a47d2a53..db70ea27d2 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-2-Clause */ +#include #include #include #include @@ -129,6 +130,14 @@ NEVER_INLINE void syscall_handler(TrapFrame* trap) { auto& regs = *trap->regs; auto current_thread = Thread::current(); + { + ScopedSpinLock lock(g_scheduler_lock); + current_thread->set_may_die_immediately(false); + } + ScopeGuard reset_may_die_immediately = [¤t_thread] { + ScopedSpinLock lock(g_scheduler_lock); + current_thread->set_may_die_immediately(true); + }; VERIFY(current_thread->previous_mode() == Thread::PreviousMode::UserMode); auto& process = current_thread->process(); diff --git a/Kernel/Thread.h b/Kernel/Thread.h index 4f6e2bc758..2f2f7f97df 100644 --- a/Kernel/Thread.h +++ b/Kernel/Thread.h @@ -1134,6 +1134,9 @@ public: bool is_profiling_suppressed() const { return m_is_profiling_suppressed; } void set_profiling_suppressed() { m_is_profiling_suppressed = true; } + bool may_die_immediately() const { return m_may_die_immediately; } + void set_may_die_immediately(bool flag) { m_may_die_immediately = flag; } + private: Thread(NonnullRefPtr, NonnullOwnPtr, NonnullRefPtr); @@ -1227,6 +1230,7 @@ private: Optional m_thread_specific_range; Array m_signal_action_data; Blocker* m_blocker { nullptr }; + bool m_may_die_immediately { true }; #if LOCK_DEBUG struct HoldingLockInfo {