From d72191ed5f276c5b1f01019d4f75fb669817618c Mon Sep 17 00:00:00 2001 From: misson20000 Date: Fri, 13 Dec 2019 12:58:28 -0800 Subject: [PATCH] pm: fix busy loop on <5.0.0 when processes exit This was caused by failing to unlink exited processes from the waitable list, so the process manager thread would loop forever on the same process signal. --- stratosphere/pm/source/impl/pm_process_info.cpp | 2 +- stratosphere/pm/source/impl/pm_process_info.hpp | 10 ++++++++++ stratosphere/pm/source/impl/pm_process_manager.cpp | 3 +++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/stratosphere/pm/source/impl/pm_process_info.cpp b/stratosphere/pm/source/impl/pm_process_info.cpp index 7bc21b720..161a5cc63 100644 --- a/stratosphere/pm/source/impl/pm_process_info.cpp +++ b/stratosphere/pm/source/impl/pm_process_info.cpp @@ -37,7 +37,7 @@ namespace ams::pm::impl { this->handle = INVALID_HANDLE; /* Unlink the process from its waitable manager. */ - this->waitable_holder.UnlinkFromWaitableManager(); + UnlinkFromWaitableManagerIfLinked(); } } diff --git a/stratosphere/pm/source/impl/pm_process_info.hpp b/stratosphere/pm/source/impl/pm_process_info.hpp index 8c15a9964..f0b4648bb 100644 --- a/stratosphere/pm/source/impl/pm_process_info.hpp +++ b/stratosphere/pm/source/impl/pm_process_info.hpp @@ -46,6 +46,7 @@ namespace ams::pm::impl { ProcessState state; u32 flags; os::WaitableHolder waitable_holder; + bool waitable_holder_is_linked = false; private: void SetFlag(Flag flag) { this->flags |= flag; @@ -64,7 +65,16 @@ namespace ams::pm::impl { void Cleanup(); void LinkToWaitableManager(os::WaitableManager &manager) { + AMS_ASSERT(!waitable_holder_is_linked); manager.LinkWaitableHolder(&this->waitable_holder); + waitable_holder_is_linked = true; + } + + void UnlinkFromWaitableManagerIfLinked() { + if (waitable_holder_is_linked) { + this->waitable_holder.UnlinkFromWaitableManager(); + waitable_holder_is_linked = false; + } } Handle GetHandle() const { diff --git a/stratosphere/pm/source/impl/pm_process_manager.cpp b/stratosphere/pm/source/impl/pm_process_manager.cpp index fecb1236a..ca606c68b 100644 --- a/stratosphere/pm/source/impl/pm_process_manager.cpp +++ b/stratosphere/pm/source/impl/pm_process_manager.cpp @@ -414,6 +414,8 @@ namespace ams::pm::impl { case ProcessState_Exited: if (hos::GetVersion() < hos::Version_500 && process_info->ShouldSignalOnExit()) { g_process_event.Signal(); + + process_info->UnlinkFromWaitableManagerIfLinked(); } else { /* Free process resources, unlink from waitable manager. */ process_info->Cleanup(); @@ -436,6 +438,7 @@ namespace ams::pm::impl { CleanupProcessInfo(list, process_info); } } + break; case ProcessState_DebugSuspended: if (process_info->ShouldSignalOnDebugEvent()) { process_info->SetSuspended();