Beispiel #1
0
/*!	\brief Initializes the roster.

	Currently only adds the registrar to the roster.
	The application must already be running, more precisly Run() must have
	been called.

	\return
	- \c B_OK: Everything went fine.
	- an error code
*/
status_t
TRoster::Init()
{
	// check lock initialization
	if (fLock.Sem() < 0)
		return fLock.Sem();

	// create the info
	RosterAppInfo* info = new(nothrow) RosterAppInfo;
	if (info == NULL)
		return B_NO_MEMORY;

	// get the app's ref
	entry_ref ref;
	status_t error = get_app_ref(&ref);

	// init and add the info
	if (error == B_OK) {
		info->Init(be_app->Thread(), be_app->Team(),
			BMessenger::Private(be_app_messenger).Port(),
			B_EXCLUSIVE_LAUNCH | B_BACKGROUND_APP, &ref, B_REGISTRAR_SIGNATURE);
		info->state = APP_STATE_REGISTERED;
		info->registration_time = system_time();
		error = AddApp(info);
	}

	if (error == B_OK)
		_LoadRosterSettings();

	// cleanup on error
	if (error != B_OK)
		delete info;

	return error;
}
Beispiel #2
0
/*!
	\brief Checks all registered apps for \a ref and \a signature if
		they are still alive, and removes those that aren't.
*/
void
TRoster::_ValidateRunning(const entry_ref& ref, const char* signature)
{
	while (true) {
		// get info via ref or signature
		RosterAppInfo* info = fRegisteredApps.InfoFor(&ref);
		if (info == NULL && signature != NULL)
			info = fRegisteredApps.InfoFor(signature);

		// if app is alive or does not exist, we can exit
		if (info == NULL || info->IsRunning())
			return;

		RemoveApp(info);
		delete info;
	}
}
Beispiel #3
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;
				}
			}
		}
	}
}
Beispiel #4
0
/*!	\brief Handles an AddApplication() request.
	\param request The request message
*/
void
TRoster::HandleAddApplication(BMessage* request)
{
	FUNCTION_START();

	BAutolock _(fLock);

	status_t error = B_OK;
	// get the parameters
	const char* signature;
	entry_ref ref;
	uint32 flags;
	team_id team;
	thread_id thread;
	port_id port;
	bool fullReg;
	if (request->FindString("signature", &signature) != B_OK)
		signature = NULL;
	if (request->FindRef("ref", &ref) != B_OK)
		SET_ERROR(error, B_BAD_VALUE);
	if (request->FindInt32("flags", (int32*)&flags) != B_OK)
		flags = B_REG_DEFAULT_APP_FLAGS;
	if (request->FindInt32("team", &team) != B_OK)
		team = -1;
	if (request->FindInt32("thread", &thread) != B_OK)
		thread = -1;
	if (request->FindInt32("port", &port) != B_OK)
		port = -1;
	if (request->FindBool("full_registration", &fullReg) != B_OK)
		fullReg = false;

	PRINT("team: %" B_PRId32 ", signature: %s\n", team, signature);
	PRINT("full registration: %d\n", fullReg);

	if (fShuttingDown)
		error = B_SHUTTING_DOWN;

	// check the parameters
	team_id otherTeam = -1;
	uint32 token = 0;

	uint32 launchFlags = flags & B_LAUNCH_MASK;
	BEntry entry(&ref);
	if (!entry.Exists())
		SET_ERROR(error, B_ENTRY_NOT_FOUND);

	if (error == B_OK)
		_ValidateRunning(ref, signature);

	// entry_ref
	if (error == B_OK) {
		PRINT("flags: %" B_PRIx32 "\n", flags);
		PRINT("ref: %" B_PRId32 ", %" B_PRId64 ", %s\n", ref.device,
			ref.directory, ref.name);
		// check single/exclusive launchers
		RosterAppInfo* info = NULL;
		if ((launchFlags == B_SINGLE_LAUNCH
			 || launchFlags ==  B_EXCLUSIVE_LAUNCH)
			&& ((info = fRegisteredApps.InfoFor(&ref)) != NULL
				|| (info = fEarlyPreRegisteredApps.InfoFor(&ref)) != NULL)) {
			SET_ERROR(error, B_ALREADY_RUNNING);
			otherTeam = info->team;
			token = info->token;
		}
	}

	// signature
	if (error == B_OK && signature) {
		// check exclusive launchers
		RosterAppInfo* info = NULL;
		if (launchFlags == B_EXCLUSIVE_LAUNCH
			&& (((info = fRegisteredApps.InfoFor(signature)))
				|| ((info = fEarlyPreRegisteredApps.InfoFor(signature))))) {
			SET_ERROR(error, B_ALREADY_RUNNING);
			otherTeam = info->team;
			token = info->token;
		}
	}

	// If no team ID is given, full registration isn't possible.
	if (error == B_OK) {
		if (team < 0) {
			if (fullReg)
				SET_ERROR(error, B_BAD_VALUE);
		} else if (fRegisteredApps.InfoFor(team))
			SET_ERROR(error, B_REG_ALREADY_REGISTERED);
	}

	// Add the application info.
	if (error == B_OK) {
		// alloc and init the info
		RosterAppInfo* info = new(nothrow) RosterAppInfo;
		if (info) {
			info->Init(thread, team, port, flags, &ref, signature);
			if (fullReg)
				info->state = APP_STATE_REGISTERED;
			else
				info->state = APP_STATE_PRE_REGISTERED;
			info->registration_time = system_time();
			// add it to the right list
			bool addingSuccess = false;
			if (team >= 0) {
				PRINT("added ref: %" B_PRId32 ", %" B_PRId64 ", %s\n",
					info->ref.device, info->ref.directory, info->ref.name);
				addingSuccess = (AddApp(info) == B_OK);
				if (addingSuccess && fullReg)
					_AppAdded(info);
			} else {
				token = info->token = _NextToken();
				addingSuccess = fEarlyPreRegisteredApps.AddInfo(info);
				PRINT("added to early pre-regs, token: %" B_PRIu32 "\n", token);
			}
			if (!addingSuccess)
				SET_ERROR(error, B_NO_MEMORY);
		} else
			SET_ERROR(error, B_NO_MEMORY);
		// delete the info on failure
		if (error != B_OK && info)
			delete info;
	}

	// reply to the request
	if (error == B_OK) {
		// add to recent apps if successful
		if (signature && signature[0] != '\0')
			fRecentApps.Add(signature, flags);
		else
			fRecentApps.Add(&ref, flags);

		BMessage reply(B_REG_SUCCESS);
		// The token is valid only when no team ID has been supplied.
		if (team < 0)
			reply.AddInt32("token", (int32)token);
		request->SendReply(&reply);
	} else {
		BMessage reply(B_REG_ERROR);
		reply.AddInt32("error", error);
		if (otherTeam >= 0)
			reply.AddInt32("other_team", otherTeam);
		if (token > 0)
			reply.AddInt32("token", (int32)token);
		request->SendReply(&reply);
	}

	FUNCTION_END();
}
Beispiel #5
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;
}