From 021fb3ea05e5be7ca814ab281409fedc16b2a18b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?kleines=20Filmr=C3=B6llchen?= Date: Tue, 27 Jun 2023 15:19:39 +0200 Subject: [PATCH] Kernel/Tasks: Allow Kernel processes to be shut down Since we never check a kernel process's state like a userland process, it's possible for a kernel process to ignore the fact that someone is trying to kill it, and continue running. This is not desireable if we want to properly shutdown all processes, including Kernel ones. --- Kernel/Bus/USB/UHCI/UHCIController.cpp | 8 ++++++-- Kernel/FileSystem/Plan9FS/FileSystem.cpp | 6 ++++-- Kernel/FileSystem/Plan9FS/FileSystem.h | 1 - Kernel/Net/NetworkTask.cpp | 4 +++- Kernel/Tasks/FinalizerTask.cpp | 4 +++- Kernel/Tasks/SyncTask.cpp | 4 +++- Kernel/Tasks/WorkQueue.cpp | 4 +++- 7 files changed, 22 insertions(+), 9 deletions(-) diff --git a/Kernel/Bus/USB/UHCI/UHCIController.cpp b/Kernel/Bus/USB/UHCI/UHCIController.cpp index 26e6e8c0aa..a98bdab23a 100644 --- a/Kernel/Bus/USB/UHCI/UHCIController.cpp +++ b/Kernel/Bus/USB/UHCI/UHCIController.cpp @@ -586,12 +586,14 @@ size_t UHCIController::poll_transfer_queue(QueueHead& transfer_queue) ErrorOr UHCIController::spawn_port_process() { TRY(Process::create_kernel_process(TRY(KString::try_create("UHCI Hot Plug Task"sv)), [&] { - for (;;) { + while (!Process::current().is_dying()) { if (m_root_hub) m_root_hub->check_for_port_updates(); (void)Thread::current()->sleep(Duration::from_seconds(1)); } + Process::current().sys$exit(0); + VERIFY_NOT_REACHED(); })); return {}; } @@ -600,7 +602,7 @@ ErrorOr UHCIController::spawn_async_poll_process() { TRY(Process::create_kernel_process(TRY(KString::try_create("UHCI Async Poll Task"sv)), [&] { u16 poll_interval_ms = 1024; - for (;;) { + while (!Process::current().is_dying()) { { SpinlockLocker locker { m_async_lock }; for (OwnPtr& handle : m_active_async_transfers) { @@ -618,6 +620,8 @@ ErrorOr UHCIController::spawn_async_poll_process() } (void)Thread::current()->sleep(Duration::from_milliseconds(poll_interval_ms)); } + Process::current().sys$exit(0); + VERIFY_NOT_REACHED(); })); return {}; } diff --git a/Kernel/FileSystem/Plan9FS/FileSystem.cpp b/Kernel/FileSystem/Plan9FS/FileSystem.cpp index bd1f70b895..8a6796344d 100644 --- a/Kernel/FileSystem/Plan9FS/FileSystem.cpp +++ b/Kernel/FileSystem/Plan9FS/FileSystem.cpp @@ -327,7 +327,7 @@ size_t Plan9FS::adjust_buffer_size(size_t size) const void Plan9FS::thread_main() { dbgln("Plan9FS: Thread running"); - do { + while (!Process::current().is_dying()) { auto result = read_and_dispatch_one_message(); if (result.is_error()) { // If we fail to read, wake up everyone with an error. @@ -342,7 +342,7 @@ void Plan9FS::thread_main() dbgln("Plan9FS: Thread terminating, error reading"); return; } - } while (!m_thread_shutdown); + } dbgln("Plan9FS: Thread terminating"); } @@ -356,6 +356,8 @@ void Plan9FS::ensure_thread() auto [_, thread] = Process::create_kernel_process(process_name.release_value(), [&]() { thread_main(); m_thread_running.store(false, AK::MemoryOrder::memory_order_release); + Process::current().sys$exit(0); + VERIFY_NOT_REACHED(); }).release_value_but_fixme_should_propagate_errors(); m_thread = move(thread); } diff --git a/Kernel/FileSystem/Plan9FS/FileSystem.h b/Kernel/FileSystem/Plan9FS/FileSystem.h index b1a48b9644..0818a757b3 100644 --- a/Kernel/FileSystem/Plan9FS/FileSystem.h +++ b/Kernel/FileSystem/Plan9FS/FileSystem.h @@ -139,7 +139,6 @@ private: Spinlock m_thread_lock {}; RefPtr m_thread; Atomic m_thread_running { false }; - Atomic m_thread_shutdown { false }; }; } diff --git a/Kernel/Net/NetworkTask.cpp b/Kernel/Net/NetworkTask.cpp index ff91e7a66f..207249121e 100644 --- a/Kernel/Net/NetworkTask.cpp +++ b/Kernel/Net/NetworkTask.cpp @@ -96,7 +96,7 @@ void NetworkTask_main(void*) auto buffer = (u8*)buffer_region->vaddr().get(); UnixDateTime packet_timestamp; - for (;;) { + while (!Process::current().is_dying()) { flush_delayed_tcp_acks(); retransmit_tcp_packets(); size_t packet_size = dequeue_packet(buffer, buffer_size, packet_timestamp); @@ -127,6 +127,8 @@ void NetworkTask_main(void*) dbgln_if(ETHERNET_DEBUG, "NetworkTask: Unknown ethernet type {:#04x}", eth.ether_type()); } } + Process::current().sys$exit(0); + VERIFY_NOT_REACHED(); } void handle_arp(EthernetFrameHeader const& eth, size_t frame_size) diff --git a/Kernel/Tasks/FinalizerTask.cpp b/Kernel/Tasks/FinalizerTask.cpp index 643ea6f1c2..2fccea664a 100644 --- a/Kernel/Tasks/FinalizerTask.cpp +++ b/Kernel/Tasks/FinalizerTask.cpp @@ -16,7 +16,7 @@ static constexpr StringView finalizer_task_name = "Finalizer Task"sv; static void finalizer_task(void*) { Thread::current()->set_priority(THREAD_PRIORITY_LOW); - for (;;) { + while (!Process::current().is_dying()) { // The order of this if-else is important: We want to continue trying to finalize the threads in case // Thread::finalize_dying_threads set g_finalizer_has_work back to true due to OOM conditions if (g_finalizer_has_work.exchange(false, AK::MemoryOrder::memory_order_acq_rel) == true) @@ -24,6 +24,8 @@ static void finalizer_task(void*) else g_finalizer_wait_queue->wait_forever(finalizer_task_name); } + Process::current().sys$exit(0); + VERIFY_NOT_REACHED(); } UNMAP_AFTER_INIT void FinalizerTask::spawn() diff --git a/Kernel/Tasks/SyncTask.cpp b/Kernel/Tasks/SyncTask.cpp index 7de469dc4c..d7574b3aef 100644 --- a/Kernel/Tasks/SyncTask.cpp +++ b/Kernel/Tasks/SyncTask.cpp @@ -16,10 +16,12 @@ UNMAP_AFTER_INIT void SyncTask::spawn() { MUST(Process::create_kernel_process(KString::must_create("VFS Sync Task"sv), [] { dbgln("VFS SyncTask is running"); - for (;;) { + while (!Process::current().is_dying()) { VirtualFileSystem::sync(); (void)Thread::current()->sleep(Duration::from_seconds(1)); } + Process::current().sys$exit(0); + VERIFY_NOT_REACHED(); })); } diff --git a/Kernel/Tasks/WorkQueue.cpp b/Kernel/Tasks/WorkQueue.cpp index fb9d358c33..e9102d0ce8 100644 --- a/Kernel/Tasks/WorkQueue.cpp +++ b/Kernel/Tasks/WorkQueue.cpp @@ -28,7 +28,7 @@ UNMAP_AFTER_INIT WorkQueue::WorkQueue(StringView name) if (name_kstring.is_error()) TODO(); auto [_, thread] = Process::create_kernel_process(name_kstring.release_value(), [this] { - for (;;) { + while (!Process::current().is_dying()) { WorkItem* item; bool have_more; m_items.with([&](auto& items) { @@ -44,6 +44,8 @@ UNMAP_AFTER_INIT WorkQueue::WorkQueue(StringView name) } [[maybe_unused]] auto result = m_wait_queue.wait_on({}); } + Process::current().sys$exit(0); + VERIFY_NOT_REACHED(); }).release_value_but_fixme_should_propagate_errors(); m_thread = move(thread); }