LinuxPower.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  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. #include "Hal.h"
  6. #include "HalLog.h"
  7. #include <unistd.h>
  8. #include <sys/reboot.h>
  9. #include "nsIObserverService.h"
  10. #include "mozilla/Services.h"
  11. #include "MainThreadUtils.h"
  12. namespace mozilla {
  13. namespace hal_impl {
  14. void
  15. Reboot()
  16. {
  17. if (NS_IsMainThread()) {
  18. nsCOMPtr<nsIObserverService> obsServ = services::GetObserverService();
  19. if (obsServ) {
  20. obsServ->NotifyObservers(nullptr, "system-reboot", nullptr);
  21. }
  22. }
  23. sync();
  24. reboot(RB_AUTOBOOT);
  25. }
  26. void
  27. PowerOff()
  28. {
  29. if (NS_IsMainThread()) {
  30. nsCOMPtr<nsIObserverService> obsServ = services::GetObserverService();
  31. if (obsServ) {
  32. obsServ->NotifyObservers(nullptr, "system-power-off", nullptr);
  33. }
  34. }
  35. sync();
  36. reboot(RB_POWER_OFF);
  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. watchdogParam(hal::ShutdownMode aMode, int32_t aTimeoutSecs)
  44. : mode(aMode), timeoutSecs(aTimeoutSecs) {}
  45. } watchdogParam_t;
  46. // Function to complusively shut down the system with a given mode.
  47. static void
  48. QuitHard(hal::ShutdownMode aMode)
  49. {
  50. switch (aMode)
  51. {
  52. case hal::eHalShutdownMode_PowerOff:
  53. PowerOff();
  54. break;
  55. case hal::eHalShutdownMode_Reboot:
  56. Reboot();
  57. break;
  58. case hal::eHalShutdownMode_Restart:
  59. // Don't let signal handlers affect forced shutdown.
  60. kill(0, SIGKILL);
  61. // If we can't SIGKILL our process group, something is badly
  62. // wrong. Trying to deliver a catch-able signal to ourselves can
  63. // invoke signal handlers and might cause problems. So try
  64. // _exit() and hope we go away.
  65. _exit(1);
  66. break;
  67. default:
  68. MOZ_CRASH();
  69. }
  70. }
  71. // Function to complusively shut down the system with a given mode when timeout.
  72. static void*
  73. ForceQuitWatchdog(void* aParamPtr)
  74. {
  75. watchdogParam_t* paramPtr = reinterpret_cast<watchdogParam_t*>(aParamPtr);
  76. if (paramPtr->timeoutSecs > 0 && paramPtr->timeoutSecs <= 30) {
  77. // If we shut down normally before the timeout, this thread will
  78. // be harmlessly reaped by the OS.
  79. TimeStamp deadline =
  80. (TimeStamp::Now() + TimeDuration::FromSeconds(paramPtr->timeoutSecs));
  81. while (true) {
  82. TimeDuration remaining = (deadline - TimeStamp::Now());
  83. int sleepSeconds = int(remaining.ToSeconds());
  84. if (sleepSeconds <= 0) {
  85. break;
  86. }
  87. sleep(sleepSeconds);
  88. }
  89. }
  90. hal::ShutdownMode mode = paramPtr->mode;
  91. delete paramPtr;
  92. QuitHard(mode);
  93. return nullptr;
  94. }
  95. void
  96. StartForceQuitWatchdog(hal::ShutdownMode aMode, int32_t aTimeoutSecs)
  97. {
  98. // Force-quits are intepreted a little more ferociously on Gonk,
  99. // because while Gecko is in the process of shutting down, the user
  100. // can't call 911, for example. And if we hang on shutdown, bad
  101. // things happen. So, make sure that doesn't happen.
  102. if (aTimeoutSecs <= 0) {
  103. return;
  104. }
  105. // Use a raw pthread here to insulate ourselves from bugs in other
  106. // Gecko code that we're trying to protect!
  107. //
  108. // Note that we let the watchdog in charge of releasing |paramPtr|
  109. // if the pthread is successfully created.
  110. watchdogParam_t* paramPtr = new watchdogParam_t(aMode, aTimeoutSecs);
  111. pthread_t watchdog;
  112. if (pthread_create(&watchdog, nullptr,
  113. ForceQuitWatchdog,
  114. reinterpret_cast<void*>(paramPtr))) {
  115. // Better safe than sorry.
  116. delete paramPtr;
  117. QuitHard(aMode);
  118. }
  119. // The watchdog thread is off and running now.
  120. }
  121. } // hal_impl
  122. } // mozilla