Return immediately for non-joining KProcess::Kills 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.
This commit is contained in:
PixelyIon 2021-10-30 18:37:50 +05:30
parent 6f59cba68d
commit 962d8dc4c8
2 changed files with 8 additions and 0 deletions

View File

@ -26,6 +26,13 @@ namespace skyline::kernel::type {
} }
void KProcess::Kill(bool join, bool all, bool disableCreation) { 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); std::lock_guard guard(threadMutex);
if (disableCreation) if (disableCreation)
disableThreadCreation = true; disableThreadCreation = true;

View File

@ -27,6 +27,7 @@ namespace skyline {
private: private:
std::mutex threadMutex; //!< Synchronizes thread creation to prevent a race between thread creation and thread killing 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 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<std::shared_ptr<KThread>> threads; std::vector<std::shared_ptr<KThread>> threads;
using SyncWaiters = std::multimap<void *, std::shared_ptr<KThread>>; using SyncWaiters = std::multimap<void *, std::shared_ptr<KThread>>;