Shutdown: follow up on ff6135f474eed07e58bbd1557cd2cd8ee8027677
* calling TRoster::GetShutdownApps() multiple times with the same lists leads to problems because the lists aren't emptied first. * instead we watch the user app launches, add them in the fUserApps list, and let _QuitApps() iterates through the fUserApps list until it is empty.
This commit is contained in:
parent
7de029128e
commit
6899a856fe
@ -593,7 +593,7 @@ private:
|
||||
ShutdownProcess::ShutdownProcess(TRoster* roster, EventQueue* eventQueue)
|
||||
:
|
||||
BLooper("shutdown process"),
|
||||
EventMaskWatcher(BMessenger(this), B_REQUEST_QUIT),
|
||||
EventMaskWatcher(BMessenger(this), B_REQUEST_QUIT | B_REQUEST_LAUNCHED),
|
||||
fWorkerLock("worker lock"),
|
||||
fRequest(NULL),
|
||||
fRoster(roster),
|
||||
@ -769,6 +769,26 @@ ShutdownProcess::MessageReceived(BMessage* message)
|
||||
break;
|
||||
}
|
||||
|
||||
case B_SOME_APP_LAUNCHED:
|
||||
{
|
||||
// get the team
|
||||
team_id team;
|
||||
if (message->FindInt32("be:team", &team) != B_OK) {
|
||||
// should not happen
|
||||
return;
|
||||
}
|
||||
|
||||
PRINT("ShutdownProcess::MessageReceived(): B_SOME_APP_LAUNCHED: %"
|
||||
B_PRId32 "\n", team);
|
||||
|
||||
// add the user app info to the respective list
|
||||
{
|
||||
BAutolock _(fWorkerLock);
|
||||
fRoster->AddAppInfo(fUserApps, team);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_PHASE_TIMED_OUT:
|
||||
{
|
||||
// get the phase the event is intended for
|
||||
@ -1232,20 +1252,6 @@ 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()
|
||||
{
|
||||
@ -1289,6 +1295,21 @@ ShutdownProcess::_WorkerDoShutdown()
|
||||
throw_error(B_SHUTDOWN_CANCELLED);
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
@ -1302,36 +1323,16 @@ 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()) {
|
||||
|
||||
// since, new apps can still be launched, loop until all are gone
|
||||
if (!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);
|
||||
|
@ -88,8 +88,6 @@ private:
|
||||
void _DisplayAbortingApp(team_id team);
|
||||
void _WaitForDebuggedTeams();
|
||||
|
||||
status_t _GetUserAndSystemAppList();
|
||||
|
||||
private:
|
||||
class TimeoutEvent;
|
||||
class InternalEvent;
|
||||
|
@ -1486,6 +1486,30 @@ TRoster::GetShutdownApps(AppInfoList& userApps, AppInfoList& systemApps,
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TRoster::AddAppInfo(AppInfoList& apps, team_id team)
|
||||
{
|
||||
BAutolock _(fLock);
|
||||
|
||||
for (AppInfoList::Iterator it(fRegisteredApps.It());
|
||||
RosterAppInfo* info = *it; ++it) {
|
||||
if (info->team == team) {
|
||||
RosterAppInfo* clonedInfo = info->Clone();
|
||||
status_t error = B_NO_MEMORY;
|
||||
if (clonedInfo != NULL) {
|
||||
if (!apps.AddInfo(clonedInfo))
|
||||
delete clonedInfo;
|
||||
else
|
||||
error = B_OK;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
return B_BAD_TEAM_ID;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TRoster::AddWatcher(Watcher* watcher)
|
||||
{
|
||||
|
@ -78,6 +78,7 @@ public:
|
||||
AppInfoList& systemApps,
|
||||
AppInfoList& backgroundApps,
|
||||
hash_set<team_id>& vitalSystemApps);
|
||||
status_t AddAppInfo(AppInfoList& apps, team_id team);
|
||||
|
||||
status_t AddWatcher(Watcher* watcher);
|
||||
void RemoveWatcher(Watcher* watcher);
|
||||
|
Loading…
x
Reference in New Issue
Block a user