michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "Hal.h" michael@0: michael@0: #include michael@0: #include michael@0: #include "nsIObserverService.h" michael@0: #include "mozilla/Services.h" michael@0: michael@0: namespace mozilla { michael@0: namespace hal_impl { michael@0: michael@0: void michael@0: Reboot() michael@0: { michael@0: nsCOMPtr obsServ = services::GetObserverService(); michael@0: if (obsServ) { michael@0: obsServ->NotifyObservers(nullptr, "system-reboot", nullptr); michael@0: } michael@0: sync(); michael@0: reboot(RB_AUTOBOOT); michael@0: } michael@0: michael@0: void michael@0: PowerOff() michael@0: { michael@0: nsCOMPtr obsServ = services::GetObserverService(); michael@0: if (obsServ) { michael@0: obsServ->NotifyObservers(nullptr, "system-power-off", nullptr); michael@0: } michael@0: sync(); michael@0: reboot(RB_POWER_OFF); michael@0: } michael@0: michael@0: // Structure to specify how watchdog pthread is going to work. michael@0: typedef struct watchdogParam michael@0: { michael@0: hal::ShutdownMode mode; // Specify how to shutdown the system. michael@0: int32_t timeoutSecs; // Specify the delayed seconds to shutdown the system. michael@0: michael@0: watchdogParam(hal::ShutdownMode aMode, int32_t aTimeoutSecs) michael@0: : mode(aMode), timeoutSecs(aTimeoutSecs) {} michael@0: } watchdogParam_t; michael@0: michael@0: // Function to complusively shut down the system with a given mode. michael@0: static void michael@0: QuitHard(hal::ShutdownMode aMode) michael@0: { michael@0: switch (aMode) michael@0: { michael@0: case hal::eHalShutdownMode_PowerOff: michael@0: PowerOff(); michael@0: break; michael@0: case hal::eHalShutdownMode_Reboot: michael@0: Reboot(); michael@0: break; michael@0: case hal::eHalShutdownMode_Restart: michael@0: // Don't let signal handlers affect forced shutdown. michael@0: kill(0, SIGKILL); michael@0: // If we can't SIGKILL our process group, something is badly michael@0: // wrong. Trying to deliver a catch-able signal to ourselves can michael@0: // invoke signal handlers and might cause problems. So try michael@0: // _exit() and hope we go away. michael@0: _exit(1); michael@0: break; michael@0: default: michael@0: MOZ_CRASH(); michael@0: } michael@0: } michael@0: michael@0: // Function to complusively shut down the system with a given mode when timeout. michael@0: static void* michael@0: ForceQuitWatchdog(void* aParamPtr) michael@0: { michael@0: watchdogParam_t* paramPtr = reinterpret_cast(aParamPtr); michael@0: if (paramPtr->timeoutSecs > 0 && paramPtr->timeoutSecs <= 30) { michael@0: // If we shut down normally before the timeout, this thread will michael@0: // be harmlessly reaped by the OS. michael@0: TimeStamp deadline = michael@0: (TimeStamp::Now() + TimeDuration::FromSeconds(paramPtr->timeoutSecs)); michael@0: while (true) { michael@0: TimeDuration remaining = (deadline - TimeStamp::Now()); michael@0: int sleepSeconds = int(remaining.ToSeconds()); michael@0: if (sleepSeconds <= 0) { michael@0: break; michael@0: } michael@0: sleep(sleepSeconds); michael@0: } michael@0: } michael@0: hal::ShutdownMode mode = paramPtr->mode; michael@0: delete paramPtr; michael@0: QuitHard(mode); michael@0: return nullptr; michael@0: } michael@0: michael@0: void michael@0: StartForceQuitWatchdog(hal::ShutdownMode aMode, int32_t aTimeoutSecs) michael@0: { michael@0: // Force-quits are intepreted a little more ferociously on Gonk, michael@0: // because while Gecko is in the process of shutting down, the user michael@0: // can't call 911, for example. And if we hang on shutdown, bad michael@0: // things happen. So, make sure that doesn't happen. michael@0: if (aTimeoutSecs <= 0) { michael@0: return; michael@0: } michael@0: michael@0: // Use a raw pthread here to insulate ourselves from bugs in other michael@0: // Gecko code that we're trying to protect! michael@0: // michael@0: // Note that we let the watchdog in charge of releasing |paramPtr| michael@0: // if the pthread is successfully created. michael@0: watchdogParam_t* paramPtr = new watchdogParam_t(aMode, aTimeoutSecs); michael@0: pthread_t watchdog; michael@0: if (pthread_create(&watchdog, nullptr, michael@0: ForceQuitWatchdog, michael@0: reinterpret_cast(paramPtr))) { michael@0: // Better safe than sorry. michael@0: delete paramPtr; michael@0: QuitHard(aMode); michael@0: } michael@0: // The watchdog thread is off and running now. michael@0: } michael@0: michael@0: } // hal_impl michael@0: } // mozilla