From 962d8dc4c8b3b3d7af3ef634d51cc77134e5e64b Mon Sep 17 00:00:00 2001 From: PixelyIon Date: Sat, 30 Oct 2021 18:37:50 +0530 Subject: [PATCH] Return immediately for non-joining `KProcess::Kill`s when already killed Locking `KProcess::threadMutex` when a process is being killed by another thread with `join` can lead to the non-joining killer effectively joining as it's waiting on the joining killer to relinquish the mutex. This has been fixed by having an atomic boolean tracking if the process has already been killed and if it has, immediately returning prior to locking the mutex for any non-joining killers. --- app/src/main/cpp/skyline/kernel/types/KProcess.cpp | 7 +++++++ app/src/main/cpp/skyline/kernel/types/KProcess.h | 1 + 2 files changed, 8 insertions(+) diff --git a/app/src/main/cpp/skyline/kernel/types/KProcess.cpp b/app/src/main/cpp/skyline/kernel/types/KProcess.cpp index 657568ca..dc740d03 100644 --- a/app/src/main/cpp/skyline/kernel/types/KProcess.cpp +++ b/app/src/main/cpp/skyline/kernel/types/KProcess.cpp @@ -26,6 +26,13 @@ namespace skyline::kernel::type { } void KProcess::Kill(bool join, bool all, bool disableCreation) { + bool expected{false}; + if (!join && !alreadyKilled.compare_exchange_strong(expected, true)) + // If the process has already been killed and we don't want to wait for it to join then just instantly return rather than waiting on the mutex + return; + else + alreadyKilled.store(true); + std::lock_guard guard(threadMutex); if (disableCreation) disableThreadCreation = true; diff --git a/app/src/main/cpp/skyline/kernel/types/KProcess.h b/app/src/main/cpp/skyline/kernel/types/KProcess.h index 70e36044..893da215 100644 --- a/app/src/main/cpp/skyline/kernel/types/KProcess.h +++ b/app/src/main/cpp/skyline/kernel/types/KProcess.h @@ -27,6 +27,7 @@ namespace skyline { private: std::mutex threadMutex; //!< Synchronizes thread creation to prevent a race between thread creation and thread killing bool disableThreadCreation{}; //!< Whether to disable thread creation, we use this to prevent thread creation after all threads have been killed + std::atomic_bool alreadyKilled{}; //!< If the process has already been killed prior so there's no need to redundantly kill it again std::vector> threads; using SyncWaiters = std::multimap>;