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 }