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

Commit 5d4d6f72 authored by Wei Wang's avatar Wei Wang
Browse files

init: Support custom shutdown actions

We have been seeing panics and errors during shutdown sequence in
some vendor's platform, and it is required to disable error handling
during shutdown.

This CL separates the shutdown request to execute another "shutdown"
trigger at the beginning of shutdown stage. And vendor can use this
trigger to add custom commands needed for shutting down gracefully.

Bug: 38203024
Bug: 62084631
Test: device reboot/shutdown
Change-Id: I3fac4ed59f06667d86e477ee55ed391cf113717f
(cherry picked from commit eeab491e)
parent f499bcdd
Loading
Loading
Loading
Loading
+7 −0
Original line number Original line Diff line number Diff line
@@ -325,6 +325,13 @@ void ActionManager::DumpState() const {
    }
    }
}
}


void ActionManager::ClearQueue() {
    // We are shutting down so don't claim the oneshot builtin actions back
    current_executing_actions_ = {};
    event_queue_ = {};
    current_command_ = 0;
}

bool ActionParser::ParseSection(std::vector<std::string>&& args, const std::string& filename,
bool ActionParser::ParseSection(std::vector<std::string>&& args, const std::string& filename,
                                int line, std::string* err) {
                                int line, std::string* err) {
    std::vector<std::string> triggers(args.begin() + 1, args.end());
    std::vector<std::string> triggers(args.begin() + 1, args.end());
+1 −0
Original line number Original line Diff line number Diff line
@@ -101,6 +101,7 @@ class ActionManager {
    void ExecuteOneCommand();
    void ExecuteOneCommand();
    bool HasMoreCommands() const;
    bool HasMoreCommands() const;
    void DumpState() const;
    void DumpState() const;
    void ClearQueue();


  private:
  private:
    ActionManager(ActionManager const&) = delete;
    ActionManager(ActionManager const&) = delete;
+1 −1
Original line number Original line Diff line number Diff line
@@ -117,7 +117,7 @@ static int reboot_into_recovery(const std::vector<std::string>& options) {
        LOG(ERROR) << "failed to set bootloader message: " << err;
        LOG(ERROR) << "failed to set bootloader message: " << err;
        return -1;
        return -1;
    }
    }
    DoReboot(ANDROID_RB_RESTART2, "reboot", "recovery", false);
    property_set("sys.powerctl", "reboot,recovery");
    return 0;
    return 0;
}
}


+16 −5
Original line number Original line Diff line number Diff line
@@ -92,6 +92,7 @@ static int epoll_fd = -1;
static std::unique_ptr<Timer> waiting_for_prop(nullptr);
static std::unique_ptr<Timer> waiting_for_prop(nullptr);
static std::string wait_prop_name;
static std::string wait_prop_name;
static std::string wait_prop_value;
static std::string wait_prop_value;
static bool shutting_down;


void DumpState() {
void DumpState() {
    ServiceManager::GetInstance().DumpState();
    ServiceManager::GetInstance().DumpState();
@@ -156,21 +157,31 @@ bool start_waiting_for_property(const char *name, const char *value)
    return true;
    return true;
}
}


void ResetWaitForProp() {
    wait_prop_name.clear();
    wait_prop_value.clear();
    waiting_for_prop.reset();
}

void property_changed(const std::string& name, const std::string& value) {
void property_changed(const std::string& name, const std::string& value) {
    // If the property is sys.powerctl, we bypass the event queue and immediately handle it.
    // If the property is sys.powerctl, we bypass the event queue and immediately handle it.
    // This is to ensure that init will always and immediately shutdown/reboot, regardless of
    // This is to ensure that init will always and immediately shutdown/reboot, regardless of
    // if there are other pending events to process or if init is waiting on an exec service or
    // if there are other pending events to process or if init is waiting on an exec service or
    // waiting on a property.
    // waiting on a property.
    if (name == "sys.powerctl") HandlePowerctlMessage(value);
    // In non-thermal-shutdown case, 'shutdown' trigger will be fired to let device specific
    // commands to be executed.
    if (name == "sys.powerctl") {
        if (HandlePowerctlMessage(value)) {
            shutting_down = true;
        }
    }


    if (property_triggers_enabled) ActionManager::GetInstance().QueuePropertyChange(name, value);
    if (property_triggers_enabled) ActionManager::GetInstance().QueuePropertyChange(name, value);


    if (waiting_for_prop) {
    if (waiting_for_prop) {
        if (wait_prop_name == name && wait_prop_value == value) {
        if (wait_prop_name == name && wait_prop_value == value) {
            wait_prop_name.clear();
            wait_prop_value.clear();
            LOG(INFO) << "Wait for property took " << *waiting_for_prop;
            LOG(INFO) << "Wait for property took " << *waiting_for_prop;
            waiting_for_prop.reset();
            ResetWaitForProp();
        }
        }
    }
    }
}
}
@@ -1157,7 +1168,7 @@ int main(int argc, char** argv) {
            am.ExecuteOneCommand();
            am.ExecuteOneCommand();
        }
        }
        if (!(waiting_for_prop || sm.IsWaitingForExec())) {
        if (!(waiting_for_prop || sm.IsWaitingForExec())) {
            restart_processes();
            if (!shutting_down) restart_processes();


            // If there's a process that needs restarting, wake up in time for that.
            // If there's a process that needs restarting, wake up in time for that.
            if (process_needs_restart_at != 0) {
            if (process_needs_restart_at != 0) {
+2 −0
Original line number Original line Diff line number Diff line
@@ -39,4 +39,6 @@ bool start_waiting_for_property(const char *name, const char *value);


void DumpState();
void DumpState();


void ResetWaitForProp();

#endif  /* _INIT_INIT_H */
#endif  /* _INIT_INIT_H */
Loading