|
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/. */ |
|
5 |
|
6 #include "Hal.h" |
|
7 |
|
8 #include <unistd.h> |
|
9 #include <sys/reboot.h> |
|
10 #include "nsIObserverService.h" |
|
11 #include "mozilla/Services.h" |
|
12 |
|
13 namespace mozilla { |
|
14 namespace hal_impl { |
|
15 |
|
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 } |
|
26 |
|
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 } |
|
37 |
|
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. |
|
43 |
|
44 watchdogParam(hal::ShutdownMode aMode, int32_t aTimeoutSecs) |
|
45 : mode(aMode), timeoutSecs(aTimeoutSecs) {} |
|
46 } watchdogParam_t; |
|
47 |
|
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 } |
|
73 |
|
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 } |
|
98 |
|
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 } |
|
109 |
|
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 } |
|
126 |
|
127 } // hal_impl |
|
128 } // mozilla |