1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 19:07:35 +00:00

Kernel: Stop leaking first thread on errors in sys$fork

Until the thread is first set as Runnable at the end of sys$fork, its
state is Invalid, and as a result, the Finalizer which is searching for
Dying threads will never find it if the syscall short-circuits due to
an error condition like OOM. This also meant the parent Process of the
thread would be leaked as well.
This commit is contained in:
Idan Horowitz 2022-07-10 16:38:34 +03:00
parent 6901d3dcec
commit c1fe844da4

View file

@ -18,6 +18,15 @@ ErrorOr<FlatPtr> Process::sys$fork(RegisterState& regs)
VERIFY_PROCESS_BIG_LOCK_ACQUIRED(this);
TRY(require_promise(Pledge::proc));
RefPtr<Thread> child_first_thread;
ArmedScopeGuard thread_finalizer_guard = [&child_first_thread]() {
SpinlockLocker lock(g_scheduler_lock);
if (child_first_thread) {
child_first_thread->detach();
child_first_thread->set_state(Thread::State::Dying);
}
};
auto child_name = TRY(m_name->try_clone());
auto child = TRY(Process::try_create(child_first_thread, move(child_name), uid(), gid(), pid(), m_is_kernel_process, current_directory(), m_executable, m_tty, this));
TRY(m_unveil_data.with([&](auto& parent_unveil_data) -> ErrorOr<void> {
@ -120,6 +129,8 @@ ErrorOr<FlatPtr> Process::sys$fork(RegisterState& regs)
}
}
thread_finalizer_guard.disarm();
Process::register_new(*child);
PerformanceManager::add_process_created_event(*child);