Wed, 31 Dec 2014 06:55:50 +0100
Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "Hal.h"
8 #include <unistd.h>
9 #include <sys/reboot.h>
10 #include "nsIObserverService.h"
11 #include "mozilla/Services.h"
13 namespace mozilla {
14 namespace hal_impl {
16 void
17 Reboot()
18 {
19 nsCOMPtr<nsIObserverService> obsServ = services::GetObserverService();
20 if (obsServ) {
21 obsServ->NotifyObservers(nullptr, "system-reboot", nullptr);
22 }
23 sync();
24 reboot(RB_AUTOBOOT);
25 }
27 void
28 PowerOff()
29 {
30 nsCOMPtr<nsIObserverService> obsServ = services::GetObserverService();
31 if (obsServ) {
32 obsServ->NotifyObservers(nullptr, "system-power-off", nullptr);
33 }
34 sync();
35 reboot(RB_POWER_OFF);
36 }
38 // Structure to specify how watchdog pthread is going to work.
39 typedef struct watchdogParam
40 {
41 hal::ShutdownMode mode; // Specify how to shutdown the system.
42 int32_t timeoutSecs; // Specify the delayed seconds to shutdown the system.
44 watchdogParam(hal::ShutdownMode aMode, int32_t aTimeoutSecs)
45 : mode(aMode), timeoutSecs(aTimeoutSecs) {}
46 } watchdogParam_t;
48 // Function to complusively shut down the system with a given mode.
49 static void
50 QuitHard(hal::ShutdownMode aMode)
51 {
52 switch (aMode)
53 {
54 case hal::eHalShutdownMode_PowerOff:
55 PowerOff();
56 break;
57 case hal::eHalShutdownMode_Reboot:
58 Reboot();
59 break;
60 case hal::eHalShutdownMode_Restart:
61 // Don't let signal handlers affect forced shutdown.
62 kill(0, SIGKILL);
63 // If we can't SIGKILL our process group, something is badly
64 // wrong. Trying to deliver a catch-able signal to ourselves can
65 // invoke signal handlers and might cause problems. So try
66 // _exit() and hope we go away.
67 _exit(1);
68 break;
69 default:
70 MOZ_CRASH();
71 }
72 }
74 // Function to complusively shut down the system with a given mode when timeout.
75 static void*
76 ForceQuitWatchdog(void* aParamPtr)
77 {
78 watchdogParam_t* paramPtr = reinterpret_cast<watchdogParam_t*>(aParamPtr);
79 if (paramPtr->timeoutSecs > 0 && paramPtr->timeoutSecs <= 30) {
80 // If we shut down normally before the timeout, this thread will
81 // be harmlessly reaped by the OS.
82 TimeStamp deadline =
83 (TimeStamp::Now() + TimeDuration::FromSeconds(paramPtr->timeoutSecs));
84 while (true) {
85 TimeDuration remaining = (deadline - TimeStamp::Now());
86 int sleepSeconds = int(remaining.ToSeconds());
87 if (sleepSeconds <= 0) {
88 break;
89 }
90 sleep(sleepSeconds);
91 }
92 }
93 hal::ShutdownMode mode = paramPtr->mode;
94 delete paramPtr;
95 QuitHard(mode);
96 return nullptr;
97 }
99 void
100 StartForceQuitWatchdog(hal::ShutdownMode aMode, int32_t aTimeoutSecs)
101 {
102 // Force-quits are intepreted a little more ferociously on Gonk,
103 // because while Gecko is in the process of shutting down, the user
104 // can't call 911, for example. And if we hang on shutdown, bad
105 // things happen. So, make sure that doesn't happen.
106 if (aTimeoutSecs <= 0) {
107 return;
108 }
110 // Use a raw pthread here to insulate ourselves from bugs in other
111 // Gecko code that we're trying to protect!
112 //
113 // Note that we let the watchdog in charge of releasing |paramPtr|
114 // if the pthread is successfully created.
115 watchdogParam_t* paramPtr = new watchdogParam_t(aMode, aTimeoutSecs);
116 pthread_t watchdog;
117 if (pthread_create(&watchdog, nullptr,
118 ForceQuitWatchdog,
119 reinterpret_cast<void*>(paramPtr))) {
120 // Better safe than sorry.
121 delete paramPtr;
122 QuitHard(aMode);
123 }
124 // The watchdog thread is off and running now.
125 }
127 } // hal_impl
128 } // mozilla