Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
/*!	\brief Checks whether the (pre-)registered applications are still running.

	This is necessary, since killed applications don't unregister properly.
*/
void
TRoster::CheckSanity()
{
	BAutolock _(fLock);

	// not early (pre-)registered applications
	AppInfoList obsoleteApps;
	for (AppInfoList::Iterator it = fRegisteredApps.It(); it.IsValid(); ++it) {
		if (!(*it)->IsRunning())
			obsoleteApps.AddInfo(*it);
	}

	// remove the apps
	for (AppInfoList::Iterator it = obsoleteApps.It(); it.IsValid(); ++it) {
		RemoveApp(*it);
		delete *it;
	}
	obsoleteApps.MakeEmpty(false);
		// don't delete infos a second time

	// early pre-registered applications
	bigtime_t timeLimit = system_time() - kMaximalEarlyPreRegistrationPeriod;
	for (AppInfoList::Iterator it = fEarlyPreRegisteredApps.It();
		 it.IsValid();
		 ++it) {
		if ((*it)->registration_time < timeLimit)
			obsoleteApps.AddInfo(*it);
	}

	// remove the apps
	for (AppInfoList::Iterator it = obsoleteApps.It(); it.IsValid(); ++it) {
		fEarlyPreRegisteredApps.RemoveInfo(*it);
		delete *it;
	}
	obsoleteApps.MakeEmpty(false);
		// don't delete infos a second time
}
Exemplo n.º 3
0
void
ShutdownProcess::_AddShutdownWindowApps(AppInfoList& infos)
{
	if (!fHasGUI)
		return;

	for (AppInfoList::Iterator it = infos.It(); it.IsValid(); ++it) {
		RosterAppInfo* info = *it;

		// init an app file info
		BFile file;
		status_t error = file.SetTo(&info->ref, B_READ_ONLY);
		if (error != B_OK) {
			WARNING(("ShutdownProcess::_AddShutdownWindowApps(): Failed to "
				"open file for app %s: %s\n", info->signature,
				strerror(error)));
			continue;
		}

		BAppFileInfo appFileInfo;
		error = appFileInfo.SetTo(&file);
		if (error != B_OK) {
			WARNING(("ShutdownProcess::_AddShutdownWindowApps(): Failed to "
				"init app file info for app %s: %s\n", info->signature,
				strerror(error)));
		}

		// get the application icons
#ifdef __HAIKU__
		color_space format = B_RGBA32;
#else
		color_space format = B_CMAP8;
#endif

		// mini icon
		BBitmap* miniIcon = new(nothrow) BBitmap(BRect(0, 0, 15, 15), format);
		if (miniIcon != NULL) {
			error = miniIcon->InitCheck();
			if (error == B_OK)
				error = appFileInfo.GetTrackerIcon(miniIcon, B_MINI_ICON);
			if (error != B_OK) {
				delete miniIcon;
				miniIcon = NULL;
			}
		}

		// mini icon
		BBitmap* largeIcon = new(nothrow) BBitmap(BRect(0, 0, 31, 31), format);
		if (largeIcon != NULL) {
			error = largeIcon->InitCheck();
			if (error == B_OK)
				error = appFileInfo.GetTrackerIcon(largeIcon, B_LARGE_ICON);
			if (error != B_OK) {
				delete largeIcon;
				largeIcon = NULL;
			}
		}

		// add the app
		error = fWindow->AddApp(info->team, miniIcon, largeIcon);
		if (error != B_OK) {
			WARNING(("ShutdownProcess::_AddShutdownWindowApps(): Failed to "
				"add app to the shutdown window: %s\n", strerror(error)));
		}
	}
}
Exemplo n.º 4
0
void
ShutdownProcess::_QuitBlockingApp(AppInfoList& list, team_id team,
	const char* appName, bool cancelAllowed)
{
	bool debugged = false;
	bool modal = false;
	{
		BAutolock _(fWorkerLock);
		if (fDebuggedTeams.find(team) != fDebuggedTeams.end())
			debugged = true;
	}
	if (!debugged)
		modal = BPrivate::is_app_showing_modal_window(team);

	if (modal) {
		// app blocks on a modal window
		BString buffer = B_TRANSLATE("The application \"%appName%\" might be "
			"blocked on a modal panel.");
		buffer.ReplaceFirst("%appName%", appName);
		_SetShutdownWindowText(buffer.String());
		_SetShutdownWindowCurrentApp(team);
		_SetShutdownWindowKillButtonEnabled(true);
	}

	if (modal || debugged) {
		// 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 || debugged) {
					PRINT(("ShutdownProcess::_QuitBlockingApp(): shutdown "
						"cancelled by team %ld (-1 => user)\n", eventTeam));

					if (!debugged)
						_DisplayAbortingApp(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;
		}
	}
}
Exemplo n.º 5
0
void
ShutdownProcess::_QuitApps(AppInfoList& list, bool systemApps)
{
	PRINT(("ShutdownProcess::_QuitApps(%s)\n",
		(systemApps ? "system" : "user")));

	if (systemApps) {
		_SetShutdownWindowCancelButtonEnabled(false);

		// check one last time for abort events
		uint32 event;
		do {
			team_id team;
			int32 phase;
			status_t error = _GetNextEvent(event, team, phase, false);
			if (error != B_OK)
				throw_error(error);

			if (event == ABORT_EVENT) {
				PRINT(("ShutdownProcess::_QuitApps(): shutdown cancelled by "
					"team %ld (-1 => user)\n", team));

				_DisplayAbortingApp(team);
				throw_error(B_SHUTDOWN_CANCELLED);
			}

		} while (event != NO_EVENT);
	}

	// prepare the shutdown message
	BMessage message;
	_PrepareShutdownMessage(message);

	// now iterate through the list of apps
	while (true) {
		// eat events
		uint32 event;
		do {
			team_id team;
			int32 phase;
			status_t error = _GetNextEvent(event, team, phase, false);
			if (error != B_OK)
				throw_error(error);

			if (!systemApps && event == ABORT_EVENT) {
				PRINT(("ShutdownProcess::_QuitApps(): shutdown cancelled by "
					"team %ld (-1 => user)\n", team));

				_DisplayAbortingApp(team);
				throw_error(B_SHUTDOWN_CANCELLED);
			}

		} while (event != NO_EVENT);

		// get the first app to quit
		team_id team = -1;
		port_id port = -1;
		char appName[B_FILE_NAME_LENGTH];
		{
			BAutolock _(fWorkerLock);
			while (!list.IsEmpty()) {
				RosterAppInfo* info = *list.It();
				team = info->team;
				port = info->port;
				strcpy(appName, info->ref.name);

				if (info->IsRunning())
					break;
				list.RemoveInfo(info);
				delete info;
			}
		}

		if (team < 0) {
			PRINT(("ShutdownProcess::_QuitApps() done\n"));
			return;
		}

		// set window text
		BString buffer = B_TRANSLATE("Asking \"%appName%\" to quit.");
		buffer.ReplaceFirst("%appName%", appName);
		_SetShutdownWindowText(buffer.String());
		_SetShutdownWindowCurrentApp(team);

		// send the shutdown message to the app
		PRINT(("  sending team %ld (port: %ld) a shutdown message\n", team,
			port));
		SingleMessagingTargetSet target(port, B_PREFERRED_TOKEN);
		MessageDeliverer::Default()->DeliverMessage(&message, target);

		// schedule a timeout event
		_ScheduleTimeoutEvent(kAppQuitTimeout, team);

		// wait for the app to die or for the timeout to occur
		bool appGone = _WaitForApp(team, &list, systemApps);
		if (appGone) {
			// fine: the app finished in an orderly manner
		} else {
			// the app is either blocking on a model alert or blocks for another
			// reason
			if (!systemApps)
				_QuitBlockingApp(list, team, appName, true);
			else {
				// This is a system app: remove it from the list
				BAutolock _(fWorkerLock);

				if (RosterAppInfo* info = list.InfoFor(team)) {
					list.RemoveInfo(info);
					delete info;
				}
			}
		}
	}
}
Exemplo n.º 6
0
/*!	\brief Returns lists of applications to be asked to quit on shutdown.

	\param userApps List of RosterAppInfos identifying the user applications.
		   Those will be ask to quit first.
	\param systemApps List of RosterAppInfos identifying the system applications
		   (like Tracker and Deskbar), which will be asked to quit after the
		   user applications are gone.
	\param vitalSystemApps A set of team_ids identifying teams that must not
		   be terminated (app server and registrar).
	\return \c B_OK, if everything went fine, another error code otherwise.
*/
status_t
TRoster::GetShutdownApps(AppInfoList& userApps, AppInfoList& systemApps,
	AppInfoList& backgroundApps, hash_set<team_id>& vitalSystemApps)
{
	BAutolock _(fLock);

	status_t error = B_OK;

	// get the vital system apps:
	// * ourself
	// * kernel team
	// * app server
	// * debug server

	// ourself
	vitalSystemApps.insert(be_app->Team());

	// kernel team
	team_info teamInfo;
	if (get_team_info(B_SYSTEM_TEAM, &teamInfo) == B_OK)
		vitalSystemApps.insert(teamInfo.team);

	// app server
	RosterAppInfo* info
		= fRegisteredApps.InfoFor("application/x-vnd.haiku-app_server");
	if (info != NULL)
		vitalSystemApps.insert(info->team);

	// debug server
	info = fRegisteredApps.InfoFor("application/x-vnd.haiku-debug_server");
	if (info != NULL)
		vitalSystemApps.insert(info->team);

	// populate the other groups
	for (AppInfoList::Iterator it(fRegisteredApps.It());
			RosterAppInfo* info = *it; ++it) {
		if (vitalSystemApps.find(info->team) == vitalSystemApps.end()) {
			RosterAppInfo* clonedInfo = info->Clone();
			if (clonedInfo) {
				if (_IsSystemApp(info)) {
					if (!systemApps.AddInfo(clonedInfo))
						error = B_NO_MEMORY;
				} else if (info->flags & B_BACKGROUND_APP) {
					if (!backgroundApps.AddInfo(clonedInfo))
						error = B_NO_MEMORY;
				} else {
					if (!userApps.AddInfo(clonedInfo))
						error = B_NO_MEMORY;
				}

				if (error != B_OK)
					delete clonedInfo;
			} else
				error = B_NO_MEMORY;
		}

		if (error != B_OK)
			break;
	}

	// Special case, we add the input server to vital apps here so it is
	// not excluded in the lists above
	info = fRegisteredApps.InfoFor("application/x-vnd.Be-input_server");
	if (info != NULL)
		vitalSystemApps.insert(info->team);

	// clean up on error
	if (error != B_OK) {
		userApps.MakeEmpty(true);
		systemApps.MakeEmpty(true);
	}

	return error;
}