diff --git a/init/builtins.cpp b/init/builtins.cpp index d77abdf52..96e78cbd4 100644 --- a/init/builtins.cpp +++ b/init/builtins.cpp @@ -267,7 +267,7 @@ static Result do_mkdir(const std::vector& args) { "--prompt_and_wipe_data", "--reason=set_policy_failed:"s + args[1]}; reboot_into_recovery(options); - return Error() << "reboot into recovery failed"; + return Success(); } } return Success(); @@ -472,7 +472,7 @@ static Result queue_fs_event(int code) { PLOG(ERROR) << "fs_mgr_mount_all suggested recovery, so wiping data via recovery."; const std::vector options = {"--wipe_data", "--reason=fs_mgr_mount_all" }; reboot_into_recovery(options); - return Error() << "reboot_into_recovery() failed"; + return Success(); /* If reboot worked, there is no return. */ } else if (code == FS_MGR_MNTALL_DEV_FILE_ENCRYPTED) { if (e4crypt_install_keyring()) { diff --git a/init/init.cpp b/init/init.cpp index c3e08fb88..817b33e75 100644 --- a/init/init.cpp +++ b/init/init.cpp @@ -79,6 +79,8 @@ static std::unique_ptr waiting_for_prop(nullptr); static std::string wait_prop_name; static std::string wait_prop_value; static bool shutting_down; +static std::string shutdown_command; +static bool do_shutdown = false; std::vector late_import_paths; @@ -157,9 +159,16 @@ 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") { - if (HandlePowerctlMessage(value)) { - shutting_down = true; - } + // Despite the above comment, we can't call HandlePowerctlMessage() 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 + // action queue. Instead we set this flag and ensure that shutdown happens before the next + // command is run in the main init loop. + // TODO: once property service is removed from init, this will never happen from a builtin, + // but rather from a callback from the property service socket, in which case this hack can + // go away. + shutdown_command = value; + do_shutdown = true; } if (property_triggers_enabled) ActionManager::GetInstance().QueuePropertyChange(name, value); @@ -622,6 +631,13 @@ int main(int argc, char** argv) { // By default, sleep until something happens. int epoll_timeout_ms = -1; + if (do_shutdown && !shutting_down) { + do_shutdown = false; + if (HandlePowerctlMessage(shutdown_command)) { + shutting_down = true; + } + } + if (!(waiting_for_prop || Service::is_exec_service_running())) { am.ExecuteOneCommand(); }