Example #1
0
void
ShutdownProcess::_WorkerDoShutdown()
{
	PRINT(("ShutdownProcess::_WorkerDoShutdown()\n"));

	// If we are here, the shutdown process has been initiated successfully,
	// that is, if an asynchronous BRoster::Shutdown() was requested, we
	// notify the caller at this point.
	bool synchronous;
	if (fRequest->FindBool("synchronous", &synchronous) == B_OK && !synchronous)
		_SendReply(B_OK);

	// ask the user to confirm the shutdown, if desired
	bool askUser;
	if (fHasGUI && fRequest->FindBool("confirm", &askUser) == B_OK && askUser) {
		const char* restart = B_TRANSLATE("Restart");
		const char* shutdown = B_TRANSLATE("Shut down");
		BString title = B_TRANSLATE("%action%?");
		title.ReplaceFirst("%action%", fReboot ? restart : shutdown);
		const char* text = fReboot
			? B_TRANSLATE("Do you really want to restart the system?")
			: B_TRANSLATE("Do you really want to shut down the system?");
		const char* defaultText = fReboot ? restart : shutdown;
		const char* otherText = fReboot ? shutdown : restart;
		BAlert* alert = new BAlert(title.String(), text,
			B_TRANSLATE("Cancel"), otherText, defaultText,
			B_WIDTH_AS_USUAL, B_WARNING_ALERT);
		alert->SetShortcut(0, B_ESCAPE);
		// We want the alert to behave more like a regular window...
		alert->SetFeel(B_NORMAL_WINDOW_FEEL);
		// ...but not quit. Minimizing the alert would prevent the user from
		// finding it again, since registrar does not have an entry in the
		// Deskbar.
		alert->SetFlags(alert->Flags() | B_NOT_MINIMIZABLE);
		alert->SetWorkspaces(B_ALL_WORKSPACES);
		int32 result = alert->Go();

		if (result == 1) {
			// Toggle shutdown method
			fReboot = !fReboot;
		} else if (result < 1)
			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);
	_SetShutdownWindowText(B_TRANSLATE("Tidying things up a bit."));
	_SetShutdownWindowCancelButtonEnabled(true);
	_SetShutdownWindowKillButtonEnabled(false);
	_SetShowShutdownWindow(true);

	// sync
	sync();

	// phase 1: terminate the user apps
	_SetPhase(USER_APP_TERMINATION_PHASE);
	_QuitApps(fUserApps, false);
	_WaitForDebuggedTeams();

	// phase 2: terminate the system apps
	_SetPhase(SYSTEM_APP_TERMINATION_PHASE);
	_QuitApps(fSystemApps, true);
	_WaitForDebuggedTeams();

	// phase 3: terminate the background apps
	_SetPhase(BACKGROUND_APP_TERMINATION_PHASE);
	_QuitBackgroundApps();
	_WaitForDebuggedTeams();

	// phase 4: terminate the other processes
	_SetPhase(OTHER_PROCESSES_TERMINATION_PHASE);
	_QuitNonApps();
	_ScheduleTimeoutEvent(kBackgroundAppQuitTimeout, -1);
	_WaitForBackgroundApps();
	_KillBackgroundApps();
	_WaitForDebuggedTeams();

	// we're through: do the shutdown
	_SetPhase(DONE_PHASE);
	if (fReboot)
		_SetShutdownWindowText(B_TRANSLATE("Restarting" B_UTF8_ELLIPSIS));
	else
		_SetShutdownWindowText(B_TRANSLATE("Shutting down" B_UTF8_ELLIPSIS));
	_ShutDown();
	_SetShutdownWindowWaitForShutdown();

	PRINT(("  _kern_shutdown() failed\n"));

	// shutdown failed: This can happen for power off mode -- reboot should
	// always work.
	if (fHasGUI) {
		// wait for the reboot event
		uint32 event;
		do {
			team_id team;
			int32 phase;
			status = _GetNextEvent(event, team, phase, true);
			if (status != B_OK)
				break;
		} while (event != REBOOT_SYSTEM_EVENT);

		_kern_shutdown(true);
	}

	// either there's no GUI or reboot failed: we enter the kernel debugger
	// instead
#ifdef __HAIKU__
// TODO: Introduce the syscall.
//	while (true) {
//		_kern_kernel_debugger("The system is shut down. It's now safe to turn "
//			"off the computer.");
//	}
#endif
}