diff --git a/src/servers/registrar/ShutdownProcess.cpp b/src/servers/registrar/ShutdownProcess.cpp index c6ae176303..f1bfff7227 100644 --- a/src/servers/registrar/ShutdownProcess.cpp +++ b/src/servers/registrar/ShutdownProcess.cpp @@ -1232,6 +1232,20 @@ ShutdownProcess::_Worker() } +status_t +ShutdownProcess::_GetUserAndSystemAppList() +{ + fWorkerLock.Lock(); + // Get a list of all applications to shut down + status_t status = fRoster->GetShutdownApps(fUserApps, fSystemApps, + fBackgroundApps, fVitalSystemApps); + fUserApps.Sort(&inverse_compare_by_registration_time); + fWorkerLock.Unlock(); + + return status; +} + + void ShutdownProcess::_WorkerDoShutdown() { @@ -1275,26 +1289,6 @@ ShutdownProcess::_WorkerDoShutdown() throw_error(B_SHUTDOWN_CANCELLED); } - // tell TRoster not to accept new applications anymore - fRoster->SetShuttingDown(true); - - fWorkerLock.Lock(); - - // get a list of all applications to shut down and sort them - status_t status = fRoster->GetShutdownApps(fUserApps, fSystemApps, - fBackgroundApps, fVitalSystemApps); - if (status != B_OK) { - fWorkerLock.Unlock(); - fRoster->RemoveWatcher(this); - fRoster->SetShuttingDown(false); - return; - } - - fUserApps.Sort(&inverse_compare_by_registration_time); - fSystemApps.Sort(&inverse_compare_by_registration_time); - - fWorkerLock.Unlock(); - // make the shutdown window ready and show it _InitShutdownWindow(); _SetShutdownWindowCurrentApp(-1); @@ -1308,9 +1302,36 @@ ShutdownProcess::_WorkerDoShutdown() // phase 1: terminate the user apps _SetPhase(USER_APP_TERMINATION_PHASE); + status_t status; + // Since, new apps can still be launched, + // loop until all are gone + while ((status = _GetUserAndSystemAppList()) == B_OK + && !fUserApps.IsEmpty()) { + _QuitApps(fUserApps, false); + _WaitForDebuggedTeams(); + } + + if (status != B_OK) { + fRoster->RemoveWatcher(this); + return; + } + + // tell TRoster not to accept new applications anymore + fRoster->SetShuttingDown(true); + + // Check once again for any user apps to quit + status = _GetUserAndSystemAppList(); + if (status != B_OK) { + fRoster->RemoveWatcher(this); + return; + } _QuitApps(fUserApps, false); _WaitForDebuggedTeams(); + fWorkerLock.Lock(); + fSystemApps.Sort(&inverse_compare_by_registration_time); + fWorkerLock.Unlock(); + // phase 2: terminate the system apps _SetPhase(SYSTEM_APP_TERMINATION_PHASE); _QuitApps(fSystemApps, true); diff --git a/src/servers/registrar/ShutdownProcess.h b/src/servers/registrar/ShutdownProcess.h index bc60f66999..259fe8fdd1 100644 --- a/src/servers/registrar/ShutdownProcess.h +++ b/src/servers/registrar/ShutdownProcess.h @@ -88,6 +88,8 @@ private: void _DisplayAbortingApp(team_id team); void _WaitForDebuggedTeams(); + status_t _GetUserAndSystemAppList(); + private: class TimeoutEvent; class InternalEvent;