From e250aaef3090d39cd0482f66146900b3d86d5024 Mon Sep 17 00:00:00 2001 From: "Justin C. Miller" Date: Sat, 18 Feb 2023 13:58:23 -0800 Subject: [PATCH] [kernel] Exit the current thread last on process exit Previously process::exit() was going through the threads in order calling thread::exit() - which blocks and never wakes if called on the current thread. Since the current thread likely belongs to the process which is exiting, and the current thread wasn't guaranteed to be last in the list, this could leave threads not cleaned up. Worse, no matter what, this caused the m_threads_lock to always be held forever on exit, keeping the scheduler from ever finishing a call to process::thread_exited() on its threads. --- src/kernel/objects/process.cpp | 16 +++++++++------- src/libraries/util/util/vector.h | 3 +++ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/kernel/objects/process.cpp b/src/kernel/objects/process.cpp index b0bc880..73c436e 100644 --- a/src/kernel/objects/process.cpp +++ b/src/kernel/objects/process.cpp @@ -52,20 +52,23 @@ process::create_kernel_process(page_table *pml4) void process::exit(int32_t code) { - util::scoped_lock lock {m_threads_lock}; - if (m_state == state::exited) return; m_state = state::exited; m_return_code = code; + thread ¤t = thread::current(); + + util::scoped_lock lock {m_threads_lock}; for (auto *thread : m_threads) { - thread->exit(); + if (thread != ¤t) + thread->exit(); } - if (this == current_cpu().process) - scheduler::get().schedule(); + lock.release(); + if (¤t.parent() == this) + current.exit(); } void @@ -123,8 +126,7 @@ process::thread_exited(thread *th) delete th; // TODO: delete the thread's stack VMA - - if (m_threads.count() == 0) { + if (m_threads.empty() && m_state != state::exited) { exit(-1); return true; } diff --git a/src/libraries/util/util/vector.h b/src/libraries/util/util/vector.h index 4082cbc..ed76f4f 100644 --- a/src/libraries/util/util/vector.h +++ b/src/libraries/util/util/vector.h @@ -82,6 +82,9 @@ public: /// Get the size of the array. inline count_t count() const { return m_size; } + /// Check if the array is empty + inline bool empty() const { return m_size == 0; } + /// Get the capacity of the array. This is the amount of space /// actually allocated. inline count_t capacity() const { return m_capacity & cap_mask; }