Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0dbfea7b authored by Tom Cherry's avatar Tom Cherry
Browse files

init: trigger shutdown directly from builtins

Especially now that property_service is a thread, there may be some
delay between when init sets sys.powerctl and when the main thread of
init receives this and triggers shutdown.  It's possible that
outstanding init commands are run during this gap and that is not
desirable.

Instead, have builtins call TriggerShutdown() directly, so we can be
sure that the next action that init runs will be to shutdown the
device.

Test: reboot works
Test: reboot into recovery due to bad /data works
Change-Id: I26fb9f4f57f46c7451b8b58187138cfedd6fd9eb
parent 6b0e789a
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -138,7 +138,14 @@ static Result<void> reboot_into_recovery(const std::vector<std::string>& options
    if (!write_bootloader_message(options, &err)) {
        return Error() << "Failed to set bootloader message: " << err;
    }
    // This function should only be reached from init and not from vendor_init, and we want to
    // immediately trigger reboot instead of relaying through property_service.  Older devices may
    // still have paths that reach here from vendor_init, so we keep the property_set as a fallback.
    if (getpid() == 1) {
        TriggerShutdown("reboot,recovery");
    } else {
        property_set("sys.powerctl", "reboot,recovery");
    }
    return {};
}

+1 −1
Original line number Diff line number Diff line
@@ -35,7 +35,7 @@ namespace android {
namespace init {

// init.h
inline void EnterShutdown(const std::string&) {
inline void TriggerShutdown(const std::string&) {
    abort();
}

+2 −2
Original line number Diff line number Diff line
@@ -179,7 +179,7 @@ void ResetWaitForProp() {
    waiting_for_prop.reset();
}

void EnterShutdown(const std::string& command) {
void TriggerShutdown(const std::string& command) {
    // We can't call HandlePowerctlMessage() directly in this function,
    // because it modifies the contents of the action queue, which can cause the action queue
    // to get into a bad state if this function is called from a command being executed by the
@@ -197,7 +197,7 @@ void property_changed(const std::string& name, const std::string& value) {
    // In non-thermal-shutdown case, 'shutdown' trigger will be fired to let device specific
    // commands to be executed.
    if (name == "sys.powerctl") {
        EnterShutdown(value);
        TriggerShutdown(value);
    }

    if (property_triggers_enabled) ActionManager::GetInstance().QueuePropertyChange(name, value);
+1 −1
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@ namespace init {
Parser CreateParser(ActionManager& action_manager, ServiceList& service_list);
Parser CreateServiceOnlyParser(ServiceList& service_list);

void EnterShutdown(const std::string& command);
void TriggerShutdown(const std::string& command);

bool start_waiting_for_property(const char *name, const char *value);

+1 −1
Original line number Diff line number Diff line
@@ -710,7 +710,7 @@ static Result<void> DoUserspaceReboot() {
    auto guard = android::base::make_scope_guard([] {
        // Leave shutdown so that we can handle a full reboot.
        LeaveShutdown();
        property_set("sys.powerctl", "reboot,abort-userspace-reboot");
        TriggerShutdown("reboot,abort-userspace-reboot");
    });
    // Triggering userspace-reboot-requested will result in a bunch of set_prop
    // actions. We should make sure, that all of them are propagated before
Loading