From afb1d68d06ce34bf120f8080af56ed0bae64f727 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 7 Apr 2021 15:16:11 -0700 Subject: [PATCH] kern: ensure handle table is finalized when deferring termination --- .../include/mesosphere/kern_k_process.hpp | 18 ++++++++++ .../libmesosphere/source/kern_k_process.cpp | 36 +++++++++++-------- 2 files changed, 39 insertions(+), 15 deletions(-) diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp index 1706a0721..43d87cbcd 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp @@ -100,6 +100,7 @@ namespace ams::kern { bool m_is_suspended{}; bool m_is_immortal{}; bool m_is_jit_debug{}; + bool m_is_handle_table_initialized{}; ams::svc::DebugEvent m_jit_debug_event_type{}; ams::svc::DebugException m_jit_debug_exception_type{}; uintptr_t m_jit_debug_params[4]{}; @@ -404,6 +405,23 @@ namespace ams::kern { this->NotifyAvailable(); } } + + ALWAYS_INLINE Result InitializeHandleTable(s32 size) { + /* Try to initialize the handle table. */ + R_TRY(m_handle_table.Initialize(size)); + + /* We succeeded, so note that we did. */ + m_is_handle_table_initialized = true; + return ResultSuccess(); + } + + ALWAYS_INLINE void FinalizeHandleTable() { + /* Finalize the table. */ + m_handle_table.Finalize(); + + /* Note that the table is finalized. */ + m_is_handle_table_initialized = false; + } }; } diff --git a/libraries/libmesosphere/source/kern_k_process.cpp b/libraries/libmesosphere/source/kern_k_process.cpp index b72c84bda..97a069a8f 100644 --- a/libraries/libmesosphere/source/kern_k_process.cpp +++ b/libraries/libmesosphere/source/kern_k_process.cpp @@ -211,19 +211,20 @@ namespace ams::kern { KSystemControl::GenerateRandomBytes(m_entropy, sizeof(m_entropy)); /* Clear remaining fields. */ - m_num_running_threads = 0; - m_num_process_switches = 0; - m_num_thread_switches = 0; - m_num_fpu_switches = 0; - m_num_supervisor_calls = 0; - m_num_ipc_messages = 0; + m_num_running_threads = 0; + m_num_process_switches = 0; + m_num_thread_switches = 0; + m_num_fpu_switches = 0; + m_num_supervisor_calls = 0; + m_num_ipc_messages = 0; - m_is_signaled = false; - m_attached_object = nullptr; - m_exception_thread = nullptr; - m_is_suspended = false; - m_memory_release_hint = 0; - m_schedule_count = 0; + m_is_signaled = false; + m_attached_object = nullptr; + m_exception_thread = nullptr; + m_is_suspended = false; + m_memory_release_hint = 0; + m_schedule_count = 0; + m_is_handle_table_initialized = false; /* We're initialized! */ m_is_initialized = true; @@ -400,6 +401,11 @@ namespace ams::kern { /* Terminate child threads. */ TerminateChildren(this, nullptr); + /* Finalize the handle table, if we're not immortal. */ + if (!m_is_immortal && m_is_handle_table_initialized) { + this->FinalizeHandleTable(); + } + /* Call the debug callback. */ KDebug::OnExitProcess(this); @@ -411,7 +417,7 @@ namespace ams::kern { /* Finalize the handle table when we're done, if the process isn't immortal. */ ON_SCOPE_EXIT { if (!m_is_immortal) { - m_handle_table.Finalize(); + this->FinalizeHandleTable(); } }; @@ -905,8 +911,8 @@ namespace ams::kern { R_TRY(m_page_table.SetMaxHeapSize(m_max_process_memory - (m_main_thread_stack_size + m_code_size))); /* Initialize our handle table. */ - R_TRY(m_handle_table.Initialize(m_capabilities.GetHandleTableSize())); - auto ht_guard = SCOPE_GUARD { m_handle_table.Finalize(); }; + R_TRY(this->InitializeHandleTable(m_capabilities.GetHandleTableSize())); + auto ht_guard = SCOPE_GUARD { this->FinalizeHandleTable(); }; /* Create a new thread for the process. */ KThread *main_thread = KThread::Create();