From cc9ed31c37935c1f2bf3b58b44d8d89d4c8fc69e Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sun, 30 Jan 2022 16:09:38 +0100 Subject: [PATCH] Kernel: Don't mark current thread as inactive after successful exec() At the end of sys$execve(), we perform a context switch from the old executable into the new executable. However, the Kernel::Thread object we are switching to is the *same* thread as the one we are switching from. So we must not assume the from_thread and to_thread are different threads. We had a bug caused by this misconception, where the "from" thread would always get marked as "inactive" when switching to a new thread. This meant that threads would always get switched into "inactive" mode on first context switch into them. If a thread then tried blocking on a kernel mutex within its first time slice, we'd end up in Thread::block(Mutex&) with an inactive thread. Once a thread is inactive, the scheduler believes it's okay to reactivate the thread (by scheduling it.) If a thread got re-scheduled prematurely while setting up a mutex block, things would fall apart and we'd crash in Thread::block() due to the thread state being "Runnable" instead of the expected "Running". --- Kernel/Scheduler.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Kernel/Scheduler.cpp b/Kernel/Scheduler.cpp index 94d2c38f9d..754f7c7911 100644 --- a/Kernel/Scheduler.cpp +++ b/Kernel/Scheduler.cpp @@ -316,7 +316,11 @@ void Scheduler::enter_current(Thread& prev_thread) auto* current_thread = Thread::current(); current_thread->update_time_scheduled(scheduler_time, true, false); - prev_thread.set_active(false); + // NOTE: When doing an exec(), we will context switch from and to the same thread! + // In that case, we must not mark the previous thread as inactive. + if (&prev_thread != current_thread) + prev_thread.set_active(false); + if (prev_thread.state() == Thread::State::Dying) { // If the thread we switched from is marked as dying, then notify // the finalizer. Note that as soon as we leave the scheduler lock