blob: 4645868d898c50f8034d044e6e2975a30c18f7e0 [file] [log] [blame] [view] [edit]
# Chrome OS Shutdown and Reboot
This document describes why and how Chrome OS devices shut down or reboot.
> "Shut down" is a verb. "Shutdown" is a noun.
## Why we shut down
### Requests from other processes
Shutdown and reboot are initiated on Chrome OS devices through `RequestShutdown`
or `RequestRestart` D-Bus method calls to `powerd`. These methods are typically
called by Chrome in response to requests from the user, but they can also be
invoked by other processes in some cases (e.g. by `update_engine` to reboot to
apply a system update, or by shell scripts in the lab to reboot devices that
don't have working network connections).
Both D-Bus methods accept two arguments:
* an int32 `power_manager::RequestShutdownReason` or
`power_manager::RequestRestartReason` value from the [powerd constants file]
in `system_api`
* a string containing a human-readable description of the reason for the
request
`powerd` logs both arguments to the [current log file] within
`/var/log/power_manager` before handling the request; look for messages like
these near the end of the file:
```
[0429/234951:INFO:daemon.cc(1175)] Got RequestShutdown message from :1.62 with reason user-request (UI request from ash)
```
```
[0425/211426:INFO:daemon.cc(1046)] Got RequestRestart message from :1.33 with reason system-update (update_engine applying update)
```
#### Sending DBus Method Calls from the CLI
Shutdown and reboot DBus method calls can be triggered in the CLI with:
* `powerd_dbus_shutdown`
* `powerd_dbus_reboot`
These executables send the `RequestShutdown` or `RequestRestart` method calls,
respectively, and can be used to test `powerd` or gracefully shutdown/reboot the
device.
### Requests within `powerd`
`powerd` may also decide to shut the system down without input from other
processes in some cases, including:
* the battery charge dropping below its shutdown threshold
* the lid being closed while Chrome has sent a policy requesting a lid-closed
action of "shut down" (e.g. because the login screen is displayed)
* the kernel repeatedly failing to suspend
* the power button being pressed while no displays are connected
In all cases, `powerd` will also log a terse message just before it shuts down
or reboots:
```
[0429/234952:INFO:daemon.cc(1606)] Shutting down, reason: user-request
```
```
[0425/211426:INFO:daemon.cc(1263)] Restarting, reason: system-update
```
## How we shut down
`powerd`'s [Daemon] class runs [powerd_setuid_helper], its setuid-root helper
binary, with `--action=shut_down` or `--action=reboot`. `powerd_setuid_helper`
runs:
```
initctl emit --no-wait runlevel RUNLEVEL=<runlevel> SHUTDOWN_REASON=<reason>
```
to instruct [Upstart] to either shut down (runlevel 0) or reboot (runlevel 6) the
system. The `SHUTDOWN_REASON` argument contains a short dash-separated string
describing the reason for the request.
The Upstart [halt job] or [reboot job] is triggered by the runlevel change. This
triggers a cascade of other jobs within Upstart's `/etc/init` directory. The
[pre-shutdown job] logs a message to `/var/log/messages` to make it easier to
see when and why the system shut down or rebooted while examining logs:
```
2018-04-24T21:30:08.513032-07:00 NOTICE pre-shutdown[22132]: Shutting down for reboot: not-via-powerd
```
> In the above case, `not-via-powerd` indicates that this clean reboot was
> initiated by the `reboot` command being run directly rather through powerd.
> Requests should always go through `powerd` when possible, both for consistency
> and for correctness (e.g. `powerd` knows to defer shutting down if a firmware
> update is in progress).
After other jobs have completed, the `halt` or `reboot` job executes the
[chromeos_shutdown] script. `chromeos_shutdown` handles various tasks:
* Remaining processes are killed.
* Partitions are unmounted.
* If powerd passed a `SHUTDOWN_REASON` argument with value `low-battery`, the
[display_low_battery_alert] script is executed to use [frecon] to display a
brief animation before shutting down.
Finally, the `halt` or `reboot` job executes the `halt` or `reboot` command with
`--force` to instruct the kernel to immediately halt or reboot the system.
[powerd constants file]: https://chromium.googlesource.com/chromiumos/platform2/system_api/+/HEAD/dbus/power_manager/dbus-constants.h
[current log file]: logging.md
[Daemon]: ../powerd/daemon.cc
[powerd_setuid_helper]: ../powerd/powerd_setuid_helper.cc
[Upstart]: http://upstart.ubuntu.com/
[halt job]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/init/upstart/halt/halt.conf
[reboot job]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/init/upstart/reboot.conf
[pre-shutdown job]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/init/upstart/pre-shutdown.conf
[chromeos_shutdown]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/init/chromeos_shutdown
[display_low_battery_alert]: https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/init/display_low_battery_alert
[frecon]: https://chromium.googlesource.com/chromiumos/platform/frecon/