diff --git a/Kernel/Process.cpp b/Kernel/Process.cpp index 491f79486c..b0a25a330d 100644 --- a/Kernel/Process.cpp +++ b/Kernel/Process.cpp @@ -181,6 +181,10 @@ RefPtr Process::create_user_process(RefPtr& first_thread, const register_new(*process); error = 0; + + // NOTE: All user processes have a leaked ref on them. It's balanced by Thread::WaitBlockCondition::finalize(). + (void)process.leak_ref(); + return process; } diff --git a/Kernel/Syscalls/fork.cpp b/Kernel/Syscalls/fork.cpp index b4782d1077..d1c3303784 100644 --- a/Kernel/Syscalls/fork.cpp +++ b/Kernel/Syscalls/fork.cpp @@ -119,9 +119,10 @@ KResultOr Process::sys$fork(RegisterState& regs) child_first_thread->set_state(Thread::State::Runnable); auto child_pid = child->pid().value(); - // We need to leak one reference so we don't destroy the Process, - // which will be dropped by Process::reap + + // NOTE: All user processes have a leaked ref on them. It's balanced by Thread::WaitBlockCondition::finalize(). (void)child.leak_ref(); + return child_pid; } diff --git a/Kernel/ThreadBlockers.cpp b/Kernel/ThreadBlockers.cpp index 1b866f33a2..9724b8b3c6 100644 --- a/Kernel/ThreadBlockers.cpp +++ b/Kernel/ThreadBlockers.cpp @@ -580,10 +580,13 @@ void Thread::WaitBlockCondition::finalize() // Clear the list of threads here so we can drop the references to them m_processes.clear(); - // No more waiters, drop the last reference immediately. This may - // cause us to be destructed ourselves! - VERIFY(m_process.ref_count() > 0); - m_process.unref(); + // NOTE: Kernel processes don't have a leaked ref on them. + if (!is_kernel_mode()) { + // No more waiters, drop the last reference immediately. This may + // cause us to be destructed ourselves! + VERIFY(m_process.ref_count() > 0); + m_process.unref(); + } } Thread::WaitBlocker::WaitBlocker(int wait_options, idtype_t id_type, pid_t id, KResultOr& result)