From 7a9018dc7a625b751345e69a52afd2a4465b612c Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 31 Dec 2020 15:53:32 -0800 Subject: [PATCH] sm: fix wait list reentrancy and state on processing loop entry --- stratosphere/sm/source/impl/sm_wait_list.cpp | 21 ++++++++++++++++++-- stratosphere/sm/source/sm_main.cpp | 2 ++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/stratosphere/sm/source/impl/sm_wait_list.cpp b/stratosphere/sm/source/impl/sm_wait_list.cpp index b43d5223c..bb6a68cb4 100644 --- a/stratosphere/sm/source/impl/sm_wait_list.cpp +++ b/stratosphere/sm/source/impl/sm_wait_list.cpp @@ -84,9 +84,14 @@ namespace ams::sm::impl { return; } + /* Get and clear the triggered service. */ + const auto resumed_service = g_triggered_service; + g_triggered_service = InvalidServiceName; + /* Process all entries. */ - for (auto &entry : g_entries) { - if (entry.service == g_triggered_service) { + for (size_t i = 0; i < util::size(g_entries); /* ... */) { + auto &entry = g_entries[i]; + if (entry.service == resumed_service) { /* Get the entry's session. */ auto * const session = entry.session; @@ -100,7 +105,19 @@ namespace ams::sm::impl { ProcessRegisterRetry(session); } } R_END_TRY_CATCH_WITH_ABORT_UNLESS; + + /* Handle nested resumes. */ + if (g_triggered_service != InvalidServiceName) { + AMS_ABORT_UNLESS(g_triggered_service == resumed_service); + + g_triggered_service = InvalidServiceName; + i = 0; + continue; + } } + + /* Advance. */ + ++i; } } diff --git a/stratosphere/sm/source/sm_main.cpp b/stratosphere/sm/source/sm_main.cpp index 35efe4092..4afd2a2e1 100644 --- a/stratosphere/sm/source/sm_main.cpp +++ b/stratosphere/sm/source/sm_main.cpp @@ -111,6 +111,7 @@ int main(int argc, char **argv) Handle smm_h; R_ABORT_UNLESS(sm::impl::RegisterServiceForSelf(&smm_h, sm::ServiceName::Encode("sm:m"), 1)); g_server_manager.RegisterServer(smm_h); + sm::impl::TestAndResume(ResumeImpl); } /*===== ATMOSPHERE EXTENSION =====*/ @@ -119,6 +120,7 @@ int main(int argc, char **argv) Handle smdmnt_h; R_ABORT_UNLESS(sm::impl::RegisterServiceForSelf(&smdmnt_h, sm::ServiceName::Encode("sm:dmnt"), 1)); g_server_manager.RegisterServer(smdmnt_h); + sm::impl::TestAndResume(ResumeImpl); } /*================================*/