mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 09:38:11 +00:00
Kernel: Unwind kernel stacks before dying
While executing in the kernel, a thread can acquire various resources that need cleanup, such as locks and references to RefCounted objects. This cleanup normally happens on the exit path, such as in destructors for various RAII guards. But we weren't calling those exit paths when killing threads that have been executing in the kernel, such as threads blocked on reading or sleeping, thus causing leaks. This commit changes how killing threads works. Now, instead of killing a thread directly, one is supposed to call thread->set_should_die(), which will unblock it and make it unwind the stack if it is blocked in the kernel. Then, just before returning to the userspace, the thread will automatically die.
This commit is contained in:
parent
00e56cda0c
commit
1e1ddce9d8
4 changed files with 58 additions and 7 deletions
|
@ -836,6 +836,7 @@ void Process::sys$exit(int status)
|
|||
m_termination_status = status;
|
||||
m_termination_signal = 0;
|
||||
die();
|
||||
current->die_if_needed();
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
|
@ -921,6 +922,7 @@ void Process::crash(int signal, u32 eip)
|
|||
{
|
||||
ASSERT_INTERRUPTS_DISABLED();
|
||||
ASSERT(!is_dead());
|
||||
ASSERT(¤t->process() == this);
|
||||
|
||||
if (m_elf_loader && ksyms_ready)
|
||||
dbgprintf("\033[31;1m%p %s\033[0m\n", eip, m_elf_loader->symbolicate(eip).characters());
|
||||
|
@ -930,6 +932,9 @@ void Process::crash(int signal, u32 eip)
|
|||
dump_regions();
|
||||
ASSERT(is_ring3());
|
||||
die();
|
||||
// We can not return from here, as there is nowhere
|
||||
// to unwind to, so die right away.
|
||||
current->die_if_needed();
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
|
@ -2320,16 +2325,13 @@ void Process::die()
|
|||
m_tracer->set_dead();
|
||||
|
||||
{
|
||||
// Tell the threads to unwind and die.
|
||||
InterruptDisabler disabler;
|
||||
for_each_thread([](Thread& thread) {
|
||||
if (thread.state() != Thread::State::Dead)
|
||||
thread.set_state(Thread::State::Dying);
|
||||
thread.set_should_die();
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
}
|
||||
|
||||
if (!Scheduler::is_active())
|
||||
Scheduler::pick_next_and_switch_now();
|
||||
}
|
||||
|
||||
size_t Process::amount_virtual() const
|
||||
|
@ -2831,9 +2833,9 @@ void Process::sys$exit_thread(void* code)
|
|||
sys$exit(0);
|
||||
return;
|
||||
}
|
||||
current->set_state(Thread::State::Dying);
|
||||
current->set_should_die();
|
||||
big_lock().unlock_if_locked();
|
||||
Scheduler::pick_next_and_switch_now();
|
||||
current->die_if_needed();
|
||||
ASSERT_NOT_REACHED();
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue