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.
This commit is contained in:
misson20000 2019-12-13 12:58:28 -08:00
parent f9a199557c
commit d72191ed5f
3 changed files with 14 additions and 1 deletions

View File

@ -37,7 +37,7 @@ namespace ams::pm::impl {
this->handle = INVALID_HANDLE; this->handle = INVALID_HANDLE;
/* Unlink the process from its waitable manager. */ /* Unlink the process from its waitable manager. */
this->waitable_holder.UnlinkFromWaitableManager(); UnlinkFromWaitableManagerIfLinked();
} }
} }

View File

@ -46,6 +46,7 @@ namespace ams::pm::impl {
ProcessState state; ProcessState state;
u32 flags; u32 flags;
os::WaitableHolder waitable_holder; os::WaitableHolder waitable_holder;
bool waitable_holder_is_linked = false;
private: private:
void SetFlag(Flag flag) { void SetFlag(Flag flag) {
this->flags |= flag; this->flags |= flag;
@ -64,7 +65,16 @@ namespace ams::pm::impl {
void Cleanup(); void Cleanup();
void LinkToWaitableManager(os::WaitableManager &manager) { void LinkToWaitableManager(os::WaitableManager &manager) {
AMS_ASSERT(!waitable_holder_is_linked);
manager.LinkWaitableHolder(&this->waitable_holder); 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 { Handle GetHandle() const {

View File

@ -414,6 +414,8 @@ namespace ams::pm::impl {
case ProcessState_Exited: case ProcessState_Exited:
if (hos::GetVersion() < hos::Version_500 && process_info->ShouldSignalOnExit()) { if (hos::GetVersion() < hos::Version_500 && process_info->ShouldSignalOnExit()) {
g_process_event.Signal(); g_process_event.Signal();
process_info->UnlinkFromWaitableManagerIfLinked();
} else { } else {
/* Free process resources, unlink from waitable manager. */ /* Free process resources, unlink from waitable manager. */
process_info->Cleanup(); process_info->Cleanup();
@ -436,6 +438,7 @@ namespace ams::pm::impl {
CleanupProcessInfo(list, process_info); CleanupProcessInfo(list, process_info);
} }
} }
break;
case ProcessState_DebugSuspended: case ProcessState_DebugSuspended:
if (process_info->ShouldSignalOnDebugEvent()) { if (process_info->ShouldSignalOnDebugEvent()) {
process_info->SetSuspended(); process_info->SetSuspended();