* Background applications are now ask to quit in parallel.

* Implemented handling of apps blocking on modal windows.
* Fixed a few bugs.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13539 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2005-07-07 15:33:20 +00:00
parent c39d6b9737
commit 6b454d971d
5 changed files with 302 additions and 96 deletions
+2 -5
View File
@@ -87,7 +87,6 @@ Registrar::~Registrar()
void void
Registrar::MessageReceived(BMessage *message) Registrar::MessageReceived(BMessage *message)
{ {
// FUNCTION_START();
switch (message->what) { switch (message->what) {
// general requests // general requests
case B_REG_GET_MIME_MESSENGER: case B_REG_GET_MIME_MESSENGER:
@@ -214,18 +213,16 @@ Registrar::MessageReceived(BMessage *message)
break; break;
case B_REG_SHUTDOWN_FINISHED: case B_REG_SHUTDOWN_FINISHED:
if (fShutdownProcess) { if (fShutdownProcess) {
if (fShutdownProcess->Lock()) { fShutdownProcess->PostMessage(B_QUIT_REQUESTED,
fShutdownProcess->Quit(); fShutdownProcess);
fShutdownProcess = NULL; fShutdownProcess = NULL;
} }
}
break; break;
default: default:
BApplication::MessageReceived(message); BApplication::MessageReceived(message);
break; break;
} }
// FUNCTION_END();
} }
// ReadyToRun // ReadyToRun
+273 -74
View File
@@ -15,6 +15,7 @@
#include <unistd.h> #include <unistd.h>
#include <AppFileInfo.h> #include <AppFileInfo.h>
#include <AppMisc.h>
#include <Autolock.h> #include <Autolock.h>
#include <Bitmap.h> #include <Bitmap.h>
#include <Button.h> #include <Button.h>
@@ -47,13 +48,18 @@
using namespace BPrivate; using namespace BPrivate;
// The time span a user application has after the quit message has been // The time span a non-background application has after the quit message has
// been delivered (more precisely: has been handed over to the
// MessageDeliverer).
static const bigtime_t kAppQuitTimeout = 3000000; // 3 s
// The time span a background application has after the quit message has been
// delivered (more precisely: has been handed over to the MessageDeliverer). // delivered (more precisely: has been handed over to the MessageDeliverer).
static const bigtime_t APP_QUIT_TIMEOUT = 3000000; // 3 s static const bigtime_t kBackgroundAppQuitTimeout = 3000000; // 3 s
// The time span non-app processes have after the HUP signal has been send // The time span non-app processes have after the HUP signal has been send
// to them before they get a KILL signal. // to them before they get a KILL signal.
static const bigtime_t NON_APP_QUIT_TIMEOUT = 500000; // 0.5 s static const bigtime_t kNonAppQuitTimeout = 500000; // 0.5 s
// message what fields // message what fields
@@ -70,8 +76,7 @@ enum {
NO_EVENT, NO_EVENT,
ABORT_EVENT, ABORT_EVENT,
TIMEOUT_EVENT, TIMEOUT_EVENT,
USER_APP_QUIT_EVENT, APP_QUIT_EVENT,
SYSTEM_APP_QUIT_EVENT,
KILL_APP_EVENT, KILL_APP_EVENT,
REBOOT_SYSTEM_EVENT, REBOOT_SYSTEM_EVENT,
}; };
@@ -81,9 +86,9 @@ enum {
INVALID_PHASE = -1, INVALID_PHASE = -1,
USER_APP_TERMINATION_PHASE = 0, USER_APP_TERMINATION_PHASE = 0,
SYSTEM_APP_TERMINATION_PHASE = 1, SYSTEM_APP_TERMINATION_PHASE = 1,
OTHER_PROCESSES_TERMINATION_PHASE = 2, BACKGROUND_APP_TERMINATION_PHASE = 2,
DONE_PHASE = 3, OTHER_PROCESSES_TERMINATION_PHASE = 3,
ABORTED_PHASE = 4, DONE_PHASE = 4,
}; };
@@ -99,6 +104,15 @@ inverse_compare_by_registration_time(const RosterAppInfo *info1,
return (cmp > 0 ? -1 : 0); return (cmp > 0 ? -1 : 0);
} }
// throw_error
/*! \brief Used to avoid type matching problems when throwing a constant.
*/
static inline
void
throw_error(status_t error)
{
throw error;
}
// TimeoutEvent // TimeoutEvent
class ShutdownProcess::TimeoutEvent : public MessageEvent { class ShutdownProcess::TimeoutEvent : public MessageEvent {
@@ -213,7 +227,8 @@ public:
B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, B_TITLED_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
B_ASYNCHRONOUS_CONTROLS | B_NOT_RESIZABLE | B_NOT_MINIMIZABLE B_ASYNCHRONOUS_CONTROLS | B_NOT_RESIZABLE | B_NOT_MINIMIZABLE
| B_NOT_ZOOMABLE | B_NOT_CLOSABLE, B_ALL_WORKSPACES), | B_NOT_ZOOMABLE | B_NOT_CLOSABLE, B_ALL_WORKSPACES),
fKillAppMessage(NULL) fKillAppMessage(NULL),
fCurrentApp(-1)
{ {
} }
@@ -298,7 +313,7 @@ public:
static const int kHSpacing = 10; static const int kHSpacing = 10;
static const int kVSpacing = 10; static const int kVSpacing = 10;
static const int kInnerHSpacing = 5; static const int kInnerHSpacing = 5;
static const int kInnerVSpacing = 2; static const int kInnerVSpacing = 8;
// buttons // buttons
fKillAppButton->ResizeToPreferred(); fKillAppButton->ResizeToPreferred();
@@ -404,6 +419,9 @@ public:
if (index < 0) if (index < 0)
return; return;
if (team == fCurrentApp)
SetCurrentApp(-1);
AppInfo *info = (AppInfo*)fAppInfos.RemoveItem(index); AppInfo *info = (AppInfo*)fAppInfos.RemoveItem(index);
delete info; delete info;
} }
@@ -412,6 +430,7 @@ public:
{ {
AppInfo *info = (team >= 0 ? _AppInfoFor(team) : NULL); AppInfo *info = (team >= 0 ? _AppInfoFor(team) : NULL);
fCurrentApp = team;
fCurrentAppIconView->SetAppInfo(info); fCurrentAppIconView->SetAppInfo(info);
fKillAppMessage->ReplaceInt32("team", team); fKillAppMessage->ReplaceInt32("team", team);
@@ -467,6 +486,9 @@ private:
int32 _AppInfoIndexOf(team_id team) int32 _AppInfoIndexOf(team_id team)
{ {
if (team < 0)
return -1;
for (int32 i = 0; AppInfo *info = (AppInfo*)fAppInfos.ItemAt(i); i++) { for (int32 i = 0; AppInfo *info = (AppInfo*)fAppInfos.ItemAt(i); i++) {
if (info->team == team) if (info->team == team)
return i; return i;
@@ -494,11 +516,13 @@ private:
virtual void Draw(BRect updateRect) virtual void Draw(BRect updateRect)
{ {
if (fAppInfo && fAppInfo->largeIcon) { SetDrawingMode(B_OP_COPY);
DrawBitmap(fAppInfo->largeIcon, BPoint(0, 0));
} else {
SetLowColor(fBackground); SetLowColor(fBackground);
FillRect(Bounds(), B_SOLID_LOW); FillRect(Bounds(), B_SOLID_LOW);
if (fAppInfo && fAppInfo->largeIcon) {
SetDrawingMode(B_OP_OVER);
DrawBitmap(fAppInfo->largeIcon, BPoint(0, 0));
} }
} }
@@ -521,6 +545,7 @@ private:
BButton *fCancelShutdownButton; BButton *fCancelShutdownButton;
BButton *fRebootSystemButton; BButton *fRebootSystemButton;
BMessage *fKillAppMessage; BMessage *fKillAppMessage;
team_id fCurrentApp;
}; };
@@ -569,6 +594,9 @@ ShutdownProcess::~ShutdownProcess()
delete fTimeoutEvent; delete fTimeoutEvent;
} }
// remove the application quit watcher
fRoster->RemoveWatcher(this);
// delete the internal event semaphore // delete the internal event semaphore
if (fInternalEventSemaphore >= 0) if (fInternalEventSemaphore >= 0)
delete_sem(fInternalEventSemaphore); delete_sem(fInternalEventSemaphore);
@@ -635,7 +663,8 @@ ShutdownProcess::Init(BMessage *request)
} }
// get a list of all applications to shut down and sort them // get a list of all applications to shut down and sort them
error = fRoster->GetShutdownApps(fUserApps, fSystemApps, fVitalSystemApps); error = fRoster->GetShutdownApps(fUserApps, fSystemApps, fBackgroundApps,
fVitalSystemApps);
if (error != B_OK) { if (error != B_OK) {
fRoster->RemoveWatcher(this); fRoster->RemoveWatcher(this);
fRoster->SetShuttingDown(false); fRoster->SetShuttingDown(false);
@@ -682,26 +711,26 @@ ShutdownProcess::MessageReceived(BMessage *message)
team)); team));
// remove the app info from the respective list // remove the app info from the respective list
_LockAppLists(); int32 phase;
RosterAppInfo *info;
{
BAutolock _(fWorkerLock);
uint32 event; info = fUserApps.InfoFor(team);
if (info)
RosterAppInfo *info = fUserApps.InfoFor(team);
if (info) {
fUserApps.RemoveInfo(info); fUserApps.RemoveInfo(info);
event = USER_APP_QUIT_EVENT; else if ((info = fSystemApps.InfoFor(team)))
} else if ((info = fSystemApps.InfoFor(team))) {
fSystemApps.RemoveInfo(info); fSystemApps.RemoveInfo(info);
event = SYSTEM_APP_QUIT_EVENT; else if ((info = fSystemApps.InfoFor(team)))
} else // not found fBackgroundApps.RemoveInfo(info);
else // not found
return; return;
int32 phase = fCurrentPhase; phase = fCurrentPhase;
}
_UnlockAppLists();
// post the event // post the event
_PushEvent(event, team, phase); _PushEvent(APP_QUIT_EVENT, team, phase);
delete info; delete info;
@@ -744,7 +773,7 @@ ShutdownProcess::MessageReceived(BMessage *message)
BAutolock _(fWorkerLock); BAutolock _(fWorkerLock);
// post the event // post the event
_PushEvent(TIMEOUT_EVENT, -1, fCurrentPhase); _PushEvent(ABORT_EVENT, -1, fCurrentPhase);
break; break;
} }
@@ -818,20 +847,6 @@ ShutdownProcess::_ScheduleTimeoutEvent(bigtime_t timeout, team_id team)
fEventQueue->AddEvent(fTimeoutEvent); fEventQueue->AddEvent(fTimeoutEvent);
} }
// _LockAppLists
bool
ShutdownProcess::_LockAppLists()
{
return fWorkerLock.Lock();
}
// _UnlockAppLists
void
ShutdownProcess::_UnlockAppLists()
{
fWorkerLock.Unlock();
}
// _SetShowShutdownWindow // _SetShowShutdownWindow
void void
ShutdownProcess::_SetShowShutdownWindow(bool show) ShutdownProcess::_SetShowShutdownWindow(bool show)
@@ -1110,7 +1125,7 @@ ShutdownProcess::_GetNextEvent(uint32 &eventType, thread_id &team, int32 &phase,
} }
// notify the window, if an app has been removed // notify the window, if an app has been removed
if (eventType == USER_APP_QUIT_EVENT || eventType == SYSTEM_APP_QUIT_EVENT) if (eventType == APP_QUIT_EVENT)
_RemoveShutdownWindowApp(team); _RemoveShutdownWindowApp(team);
return B_OK; return B_OK;
@@ -1131,7 +1146,7 @@ ShutdownProcess::_Worker()
_WorkerDoShutdown(); _WorkerDoShutdown();
fShutdownError = B_OK; fShutdownError = B_OK;
} catch (status_t error) { } catch (status_t error) {
PRINT(("ShutdownProcess::_Worker(): caught exception: %s\n", PRINT(("ShutdownProcess::_Worker(): error while shutting down: %s\n",
strerror(error))); strerror(error)));
fShutdownError = error; fShutdownError = error;
@@ -1170,10 +1185,17 @@ ShutdownProcess::_WorkerDoShutdown()
_SetPhase(SYSTEM_APP_TERMINATION_PHASE); _SetPhase(SYSTEM_APP_TERMINATION_PHASE);
_QuitApps(fSystemApps, true); _QuitApps(fSystemApps, true);
// phase 3: terminate the other processes // phase 3: terminate the background apps
_SetPhase(OTHER_PROCESSES_TERMINATION_PHASE); _SetPhase(BACKGROUND_APP_TERMINATION_PHASE);
_QuitNonApps(); _QuitNonApps();
// phase 4: terminate the other processes
_SetPhase(OTHER_PROCESSES_TERMINATION_PHASE);
_QuitBackgroundApps();
_ScheduleTimeoutEvent(kBackgroundAppQuitTimeout, -1);
_WaitForBackgroundApps();
_KillBackgroundApps();
// we're through: do the shutdown // we're through: do the shutdown
_SetPhase(DONE_PHASE); _SetPhase(DONE_PHASE);
_ShutDown(); _ShutDown();
@@ -1228,10 +1250,14 @@ ShutdownProcess::_QuitApps(AppInfoList &list, bool disableCancel)
int32 phase; int32 phase;
status_t error = _GetNextEvent(event, team, phase, false); status_t error = _GetNextEvent(event, team, phase, false);
if (error != B_OK) if (error != B_OK)
throw error; throw_error(error);
if (event == ABORT_EVENT) if (event == ABORT_EVENT) {
throw B_SHUTDOWN_CANCELLED; PRINT(("ShutdownProcess::_QuitApps(): shutdown cancelled by "
"team %ld (-1 => user)\n", team));
throw_error(B_SHUTDOWN_CANCELLED);
}
} while (event != NO_EVENT); } while (event != NO_EVENT);
} }
@@ -1249,27 +1275,30 @@ ShutdownProcess::_QuitApps(AppInfoList &list, bool disableCancel)
int32 phase; int32 phase;
status_t error = _GetNextEvent(event, team, phase, false); status_t error = _GetNextEvent(event, team, phase, false);
if (error != B_OK) if (error != B_OK)
throw error; throw_error(error);
if (!disableCancel && event == ABORT_EVENT) if (!disableCancel && event == ABORT_EVENT) {
throw B_SHUTDOWN_CANCELLED; PRINT(("ShutdownProcess::_QuitApps(): shutdown cancelled by "
"team %ld (-1 => user)\n", team));
throw_error(B_SHUTDOWN_CANCELLED);
}
} while (event != NO_EVENT); } while (event != NO_EVENT);
// get the first app to quit // get the first app to quit
_LockAppLists();
team_id team = -1; team_id team = -1;
port_id port = -1; port_id port = -1;
char appName[B_FILE_NAME_LENGTH]; char appName[B_FILE_NAME_LENGTH];
{
BAutolock _(fWorkerLock);
if (!list.IsEmpty()) { if (!list.IsEmpty()) {
RosterAppInfo *info = *list.It(); RosterAppInfo *info = *list.It();
team = info->team; team = info->team;
port = info->port; port = info->port;
strcpy(appName, info->ref.name); strcpy(appName, info->ref.name);
} }
}
_UnlockAppLists();
if (team < 0) { if (team < 0) {
PRINT(("ShutdownProcess::_QuitApps() done\n")); PRINT(("ShutdownProcess::_QuitApps() done\n"));
@@ -1289,7 +1318,7 @@ ShutdownProcess::_QuitApps(AppInfoList &list, bool disableCancel)
MessageDeliverer::Default()->DeliverMessage(&message, target); MessageDeliverer::Default()->DeliverMessage(&message, target);
// schedule a timeout event // schedule a timeout event
_ScheduleTimeoutEvent(APP_QUIT_TIMEOUT, team); _ScheduleTimeoutEvent(kAppQuitTimeout, team);
// wait for the app to die or for the timeout to occur // wait for the app to die or for the timeout to occur
bool appGone = false; bool appGone = false;
@@ -1298,9 +1327,9 @@ ShutdownProcess::_QuitApps(AppInfoList &list, bool disableCancel)
int32 phase; int32 phase;
status_t error = _GetNextEvent(event, eventTeam, phase, true); status_t error = _GetNextEvent(event, eventTeam, phase, true);
if (error != B_OK) if (error != B_OK)
throw error; throw_error(error);
if ((event == SYSTEM_APP_QUIT_EVENT || event == USER_APP_QUIT_EVENT) if ((event == APP_QUIT_EVENT)
&& eventTeam == team) { && eventTeam == team) {
appGone = true; appGone = true;
} }
@@ -1316,7 +1345,10 @@ ShutdownProcess::_QuitApps(AppInfoList &list, bool disableCancel)
if (eventTeam == team) if (eventTeam == team)
break; break;
} else { } else {
throw B_SHUTDOWN_CANCELLED; PRINT(("ShutdownProcess::_QuitApps(): shutdown cancelled "
"by team %ld (-1 => user)\n", eventTeam));
throw_error(B_SHUTDOWN_CANCELLED);
} }
} }
@@ -1329,26 +1361,122 @@ ShutdownProcess::_QuitApps(AppInfoList &list, bool disableCancel)
// TODO: check whether the app blocks on a modal alert // TODO: check whether the app blocks on a modal alert
if (appGone) { if (appGone) {
// fine: the app finished in an orderly manner // fine: the app finished in an orderly manner
} else if (false) {
// app blocks on a modal window
// ...
} else { } else {
// it does not: kill it // the app is either blocking on a model alert or blocks for another
PRINT((" killing team %ld\n", team)); // reason
_QuitBlockingApp(list, team, appName, !disableCancel);
}
}
}
kill_team(team); // _QuitBackgroundApps
void
ShutdownProcess::_QuitBackgroundApps()
{
PRINT(("ShutdownProcess::_QuitBackgroundApps()\n"));
// remove the app (the roster will note eventually and send us _SetShutdownWindowText("Asking background applications to quit.");
// a notification, but we want to be sure)
_LockAppLists();
if (RosterAppInfo *info = list.InfoFor(team)) { // prepare the shutdown message
list.RemoveInfo(info); BMessage message;
delete info; _PrepareShutdownMessage(message);
// send shutdown messages to user apps
BAutolock _(fWorkerLock);
AppInfoListMessagingTargetSet targetSet(fBackgroundApps);
if (targetSet.HasNext()) {
PRINT((" sending shutdown message to %ld apps\n",
fBackgroundApps.CountInfos()));
status_t error = MessageDeliverer::Default()->DeliverMessage(
&message, targetSet);
if (error != B_OK) {
WARNING(("_QuitBackgroundApps::_Worker(): Failed to deliver "
"shutdown message to all applications: %s\n",
strerror(error)));
}
} }
_UnlockAppLists(); PRINT(("ShutdownProcess::_QuitBackgroundApps() done\n"));
}
// _WaitForBackgroundApps
void
ShutdownProcess::_WaitForBackgroundApps()
{
PRINT(("ShutdownProcess::_WaitForBackgroundApps()\n"));
// wait for user apps
bool moreApps = true;
while (moreApps) {
{
BAutolock _(fWorkerLock);
moreApps = !fBackgroundApps.IsEmpty();
} }
if (moreApps) {
uint32 event;
team_id team;
int32 phase;
status_t error = _GetNextEvent(event, team, phase, true);
if (error != B_OK)
throw_error(error);
if (event == ABORT_EVENT) {
// ignore: it's too late to abort the shutdown
}
if (event == TIMEOUT_EVENT)
return;
}
}
PRINT(("ShutdownProcess::_WaitForBackgroundApps() done\n"));
}
// _KillBackgroundApps
void
ShutdownProcess::_KillBackgroundApps()
{
PRINT(("ShutdownProcess::_KillBackgroundApps()\n"));
while (true) {
// eat events (we need to be responsive for an abort event)
uint32 event;
do {
team_id team;
int32 phase;
status_t error = _GetNextEvent(event, team, phase, false);
if (error != B_OK)
throw_error(error);
} while (event != NO_EVENT);
// get the first team to kill
team_id team = -1;
char appName[B_FILE_NAME_LENGTH];
AppInfoList &list = fBackgroundApps;
{
BAutolock _(fWorkerLock);
if (!list.IsEmpty()) {
RosterAppInfo *info = *list.It();
team = info->team;
strcpy(appName, info->ref.name);
}
}
if (team < 0) {
PRINT(("ShutdownProcess::_KillBackgroundApps() done\n"));
return;
}
// the app is either blocking on a model alert or blocks for another
// reason
_QuitBlockingApp(list, team, appName, false);
} }
} }
@@ -1380,7 +1508,7 @@ ShutdownProcess::_QuitNonApps()
// give them a bit of time to terminate // give them a bit of time to terminate
// TODO: Instead of just waiting we could periodically check whether the // TODO: Instead of just waiting we could periodically check whether the
// processes are already gone to shorten the process. // processes are already gone to shorten the process.
snooze(NON_APP_QUIT_TIMEOUT); snooze(kNonAppQuitTimeout);
// iterate through the remaining teams and kill them // iterate through the remaining teams and kill them
cookie = 0; cookie = 0;
@@ -1400,3 +1528,74 @@ ShutdownProcess::_QuitNonApps()
PRINT(("ShutdownProcess::_QuitNonApps() done\n")); PRINT(("ShutdownProcess::_QuitNonApps() done\n"));
} }
// _QuitBlockingApp
void
ShutdownProcess::_QuitBlockingApp(AppInfoList &list, team_id team,
const char *appName, bool cancelAllowed)
{
if (BPrivate::is_app_showing_modal_window(team)) {
// app blocks on a modal window
char buffer[1024];
snprintf(buffer, sizeof(buffer), "The application \"%s\" might be "
"blocked on a modal panel.", appName);
_SetShutdownWindowText(buffer);
_SetShutdownWindowCurrentApp(team);
_SetShutdownWindowKillButtonEnabled(true);
// wait for something to happen
bool appGone = false;
while (true) {
uint32 event;
team_id eventTeam;
int32 phase;
status_t error = _GetNextEvent(event, eventTeam, phase, true);
if (error != B_OK)
throw_error(error);
if ((event == APP_QUIT_EVENT) && eventTeam == team) {
appGone = true;
break;
}
if (event == KILL_APP_EVENT && eventTeam == team)
break;
if (event == ABORT_EVENT) {
if (cancelAllowed) {
PRINT(("ShutdownProcess::_QuitBlockingApp(): shutdown "
"cancelled by team %ld (-1 => user)\n", eventTeam));
throw_error(B_SHUTDOWN_CANCELLED);
}
// If the app requests aborting the shutdown, we don't need
// to wait any longer. It has processed the request and
// won't quit by itself. We'll have to kill it.
if (eventTeam == team)
break;
}
}
_SetShutdownWindowKillButtonEnabled(false);
if (appGone)
return;
}
// kill the app
PRINT((" killing team %ld\n", team));
kill_team(team);
// remove the app (the roster will note eventually and send us
// a notification, but we want to be sure)
{
BAutolock _(fWorkerLock);
if (RosterAppInfo *info = list.InfoFor(team)) {
list.RemoveInfo(info);
delete info;
}
}
}
+6
View File
@@ -62,7 +62,12 @@ private:
void _WorkerDoShutdown(); void _WorkerDoShutdown();
void _QuitApps(AppInfoList &list, bool disableCancel); void _QuitApps(AppInfoList &list, bool disableCancel);
void _QuitBackgroundApps();
void _WaitForBackgroundApps();
void _KillBackgroundApps();
void _QuitNonApps(); void _QuitNonApps();
void _QuitBlockingApp(AppInfoList &list, team_id app, const char *appName,
bool cancelAllowed);
private: private:
class TimeoutEvent; class TimeoutEvent;
@@ -81,6 +86,7 @@ private:
hash_set<team_id> fVitalSystemApps; hash_set<team_id> fVitalSystemApps;
AppInfoList fSystemApps; AppInfoList fSystemApps;
AppInfoList fUserApps; AppInfoList fUserApps;
AppInfoList fBackgroundApps;
TimeoutEvent *fTimeoutEvent; TimeoutEvent *fTimeoutEvent;
InternalEventList *fInternalEvents; InternalEventList *fInternalEvents;
sem_id fInternalEventSemaphore; sem_id fInternalEventSemaphore;
+6 -2
View File
@@ -17,6 +17,7 @@
#include <MessagePrivate.h> #include <MessagePrivate.h>
#include <MessengerPrivate.h> #include <MessengerPrivate.h>
#include <Path.h> #include <Path.h>
#include <Roster.h> // for B_BACKGROUND_APP
#include <ServerProtocol.h> #include <ServerProtocol.h>
#include <storage_support.h> #include <storage_support.h>
@@ -1287,7 +1288,7 @@ TRoster::SetShuttingDown(bool shuttingDown)
*/ */
status_t status_t
TRoster::GetShutdownApps(AppInfoList &userApps, AppInfoList &systemApps, TRoster::GetShutdownApps(AppInfoList &userApps, AppInfoList &systemApps,
hash_set<team_id> &vitalSystemApps) AppInfoList &backgroundApps, hash_set<team_id> &vitalSystemApps)
{ {
BAutolock _(fLock); BAutolock _(fLock);
@@ -1317,7 +1318,10 @@ TRoster::GetShutdownApps(AppInfoList &userApps, AppInfoList &systemApps,
} else { } else {
RosterAppInfo *clonedInfo = info->Clone(); RosterAppInfo *clonedInfo = info->Clone();
if (clonedInfo) { if (clonedInfo) {
if (_IsSystemApp(info)) { if (info->flags & B_BACKGROUND_APP) {
if (!backgroundApps.AddInfo(clonedInfo))
error = B_NO_MEMORY;
} else if (_IsSystemApp(info)) {
if (!systemApps.AddInfo(clonedInfo)) if (!systemApps.AddInfo(clonedInfo))
error = B_NO_MEMORY; error = B_NO_MEMORY;
} else { } else {
+1 -1
View File
@@ -91,7 +91,7 @@ public:
void SetShuttingDown(bool shuttingDown); void SetShuttingDown(bool shuttingDown);
status_t GetShutdownApps(AppInfoList &userApps, AppInfoList &systemApps, status_t GetShutdownApps(AppInfoList &userApps, AppInfoList &systemApps,
hash_set<team_id> &vitalSystemApps); AppInfoList &backgroundApps, hash_set<team_id> &vitalSystemApps);
status_t AddWatcher(Watcher *watcher); status_t AddWatcher(Watcher *watcher);
void RemoveWatcher(Watcher *watcher); void RemoveWatcher(Watcher *watcher);