[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.
This commit is contained in:
Justin C. Miller
2023-02-18 13:58:23 -08:00
parent 7b29ba7d23
commit e250aaef30
2 changed files with 12 additions and 7 deletions

View File

@@ -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 &current = thread::current();
util::scoped_lock lock {m_threads_lock};
for (auto *thread : m_threads) {
thread->exit();
if (thread != &current)
thread->exit();
}
if (this == current_cpu().process)
scheduler::get().schedule();
lock.release();
if (&current.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;
}