Merge "init: make triggering shutdown from vendor_init better"
This commit is contained in:
commit
b34291bcb6
|
@ -140,14 +140,7 @@ 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");
|
||||
}
|
||||
trigger_shutdown("reboot,recovery");
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -554,7 +547,7 @@ static Result<void> queue_fs_event(int code, bool userdata_remount) {
|
|||
// support userdata remount on FDE devices, this should never been triggered. Time to
|
||||
// panic!
|
||||
LOG(ERROR) << "Userdata remount is not supported on FDE devices. How did you get here?";
|
||||
TriggerShutdown("reboot,requested-userdata-remount-on-fde-device");
|
||||
trigger_shutdown("reboot,requested-userdata-remount-on-fde-device");
|
||||
}
|
||||
ActionManager::GetInstance().QueueEventTrigger("encrypt");
|
||||
return {};
|
||||
|
@ -564,7 +557,7 @@ static Result<void> queue_fs_event(int code, bool userdata_remount) {
|
|||
// don't support userdata remount on FDE devices, this should never been triggered.
|
||||
// Time to panic!
|
||||
LOG(ERROR) << "Userdata remount is not supported on FDE devices. How did you get here?";
|
||||
TriggerShutdown("reboot,requested-userdata-remount-on-fde-device");
|
||||
trigger_shutdown("reboot,requested-userdata-remount-on-fde-device");
|
||||
}
|
||||
property_set("ro.crypto.state", "encrypted");
|
||||
property_set("ro.crypto.type", "block");
|
||||
|
@ -1148,7 +1141,7 @@ static Result<void> do_remount_userdata(const BuiltinArguments& args) {
|
|||
}
|
||||
// TODO(b/135984674): check that fstab contains /data.
|
||||
if (auto rc = fs_mgr_remount_userdata_into_checkpointing(&fstab); rc < 0) {
|
||||
TriggerShutdown("reboot,mount-userdata-failed");
|
||||
trigger_shutdown("reboot,mount-userdata-failed");
|
||||
}
|
||||
if (auto result = queue_fs_event(initial_mount_fstab_return_code, true); !result) {
|
||||
return Error() << "queue_fs_event() failed: " << result.error();
|
||||
|
|
|
@ -35,11 +35,6 @@
|
|||
namespace android {
|
||||
namespace init {
|
||||
|
||||
// init.h
|
||||
inline void TriggerShutdown(const std::string&) {
|
||||
abort();
|
||||
}
|
||||
|
||||
// property_service.h
|
||||
inline bool CanReadProperty(const std::string&, const std::string&) {
|
||||
return true;
|
||||
|
|
|
@ -180,7 +180,7 @@ void ResetWaitForProp() {
|
|||
waiting_for_prop.reset();
|
||||
}
|
||||
|
||||
void TriggerShutdown(const std::string& command) {
|
||||
static 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
|
||||
|
@ -681,6 +681,8 @@ int SecondStageMain(int argc, char** argv) {
|
|||
|
||||
boot_clock::time_point start_time = boot_clock::now();
|
||||
|
||||
trigger_shutdown = TriggerShutdown;
|
||||
|
||||
SetStdioToDevNull(argv);
|
||||
InitKernelLogging(argv);
|
||||
LOG(INFO) << "init second stage started!";
|
||||
|
|
|
@ -31,8 +31,6 @@ namespace init {
|
|||
Parser CreateParser(ActionManager& action_manager, ServiceList& service_list);
|
||||
Parser CreateServiceOnlyParser(ServiceList& service_list);
|
||||
|
||||
void TriggerShutdown(const std::string& command);
|
||||
|
||||
bool start_waiting_for_property(const char *name, const char *value);
|
||||
|
||||
void DumpState();
|
||||
|
|
|
@ -731,7 +731,7 @@ static Result<void> DoUserspaceReboot() {
|
|||
auto guard = android::base::make_scope_guard([] {
|
||||
// Leave shutdown so that we can handle a full reboot.
|
||||
LeaveShutdown();
|
||||
TriggerShutdown("reboot,abort-userspace-reboot");
|
||||
trigger_shutdown("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
|
||||
|
|
|
@ -43,7 +43,6 @@
|
|||
#if defined(__ANDROID__)
|
||||
#include <ApexProperties.sysprop.h>
|
||||
|
||||
#include "init.h"
|
||||
#include "mount_namespace.h"
|
||||
#include "property_service.h"
|
||||
#else
|
||||
|
@ -260,7 +259,7 @@ void Service::Reap(const siginfo_t& siginfo) {
|
|||
|
||||
if ((siginfo.si_code != CLD_EXITED || siginfo.si_status != 0) && on_failure_reboot_target_) {
|
||||
LOG(ERROR) << "Service with 'reboot_on_failure' option failed, shutting down system.";
|
||||
TriggerShutdown(*on_failure_reboot_target_);
|
||||
trigger_shutdown(*on_failure_reboot_target_);
|
||||
}
|
||||
|
||||
if (flags_ & SVC_EXEC) UnSetExec();
|
||||
|
@ -340,7 +339,7 @@ void Service::DumpState() const {
|
|||
Result<void> Service::ExecStart() {
|
||||
auto reboot_on_failure = make_scope_guard([this] {
|
||||
if (on_failure_reboot_target_) {
|
||||
TriggerShutdown(*on_failure_reboot_target_);
|
||||
trigger_shutdown(*on_failure_reboot_target_);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -371,7 +370,7 @@ Result<void> Service::ExecStart() {
|
|||
Result<void> Service::Start() {
|
||||
auto reboot_on_failure = make_scope_guard([this] {
|
||||
if (on_failure_reboot_target_) {
|
||||
TriggerShutdown(*on_failure_reboot_target_);
|
||||
trigger_shutdown(*on_failure_reboot_target_);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -51,6 +51,8 @@ namespace android {
|
|||
namespace init {
|
||||
namespace {
|
||||
|
||||
std::string shutdown_command;
|
||||
|
||||
class SubcontextProcess {
|
||||
public:
|
||||
SubcontextProcess(const BuiltinFunctionMap* function_map, std::string context, int init_fd)
|
||||
|
@ -153,6 +155,11 @@ void SubcontextProcess::MainLoop() {
|
|||
<< subcontext_command.command_case();
|
||||
}
|
||||
|
||||
if (!shutdown_command.empty()) {
|
||||
reply.set_trigger_shutdown(shutdown_command);
|
||||
shutdown_command.clear();
|
||||
}
|
||||
|
||||
if (auto result = SendMessage(init_fd_, reply); !result) {
|
||||
LOG(FATAL) << "Failed to send message to init: " << result.error();
|
||||
}
|
||||
|
@ -174,6 +181,8 @@ int SubcontextMain(int argc, char** argv, const BuiltinFunctionMap* function_map
|
|||
return 0;
|
||||
};
|
||||
|
||||
trigger_shutdown = [](const std::string& command) { shutdown_command = command; };
|
||||
|
||||
auto subcontext_process = SubcontextProcess(function_map, context, init_fd);
|
||||
subcontext_process.MainLoop();
|
||||
return 0;
|
||||
|
@ -254,6 +263,11 @@ Result<SubcontextReply> Subcontext::TransmitMessage(const SubcontextCommand& sub
|
|||
Restart();
|
||||
return Error() << "Unable to parse message from subcontext";
|
||||
}
|
||||
|
||||
if (subcontext_reply.has_trigger_shutdown()) {
|
||||
trigger_shutdown(subcontext_reply.trigger_shutdown());
|
||||
}
|
||||
|
||||
return subcontext_reply;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,4 +38,6 @@ message SubcontextReply {
|
|||
Failure failure = 2;
|
||||
ExpandArgsReply expand_args_reply = 3;
|
||||
}
|
||||
|
||||
optional string trigger_shutdown = 4;
|
||||
}
|
|
@ -26,6 +26,7 @@
|
|||
#include <selinux/selinux.h>
|
||||
|
||||
#include "builtin_arguments.h"
|
||||
#include "util.h"
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
|
@ -142,6 +143,18 @@ TEST(subcontext, ContextString) {
|
|||
});
|
||||
}
|
||||
|
||||
TEST(subcontext, TriggerShutdown) {
|
||||
static constexpr const char kTestShutdownCommand[] = "reboot,test-shutdown-command";
|
||||
static std::string trigger_shutdown_command;
|
||||
trigger_shutdown = [](const std::string& command) { trigger_shutdown_command = command; };
|
||||
RunTest([](auto& subcontext, auto& context_string) {
|
||||
auto result = subcontext.Execute(
|
||||
std::vector<std::string>{"trigger_shutdown", kTestShutdownCommand});
|
||||
ASSERT_TRUE(result);
|
||||
});
|
||||
EXPECT_EQ(kTestShutdownCommand, trigger_shutdown_command);
|
||||
}
|
||||
|
||||
TEST(subcontext, ExpandArgs) {
|
||||
RunTest([](auto& subcontext, auto& context_string) {
|
||||
auto args = std::vector<std::string>{
|
||||
|
@ -207,6 +220,11 @@ BuiltinFunctionMap BuildTestFunctionMap() {
|
|||
return Error() << args.context;
|
||||
};
|
||||
|
||||
auto do_trigger_shutdown = [](const BuiltinArguments& args) -> Result<void> {
|
||||
trigger_shutdown(args[1]);
|
||||
return {};
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
BuiltinFunctionMap test_function_map = {
|
||||
{"return_pids_as_error", {0, 0, {true, do_return_pids_as_error}}},
|
||||
|
@ -216,6 +234,7 @@ BuiltinFunctionMap BuildTestFunctionMap() {
|
|||
{"cause_log_fatal", {0, 0, {true, do_cause_log_fatal}}},
|
||||
{"generate_sane_error", {0, 0, {true, do_generate_sane_error}}},
|
||||
{"return_context_as_error", {0, 0, {true, do_return_context_as_error}}},
|
||||
{"trigger_shutdown", {1, 1, {true, do_trigger_shutdown}}},
|
||||
};
|
||||
// clang-format on
|
||||
return test_function_map;
|
||||
|
|
|
@ -61,6 +61,8 @@ namespace init {
|
|||
|
||||
const std::string kDefaultAndroidDtDir("/proc/device-tree/firmware/android/");
|
||||
|
||||
void (*trigger_shutdown)(const std::string& command) = nullptr;
|
||||
|
||||
// DecodeUid() - decodes and returns the given string, which can be either the
|
||||
// numeric or name representation, into the integer uid or gid.
|
||||
Result<uid_t> DecodeUid(const std::string& name) {
|
||||
|
|
|
@ -35,6 +35,8 @@ namespace init {
|
|||
|
||||
static const char kColdBootDoneProp[] = "ro.cold_boot_done";
|
||||
|
||||
extern void (*trigger_shutdown)(const std::string& command);
|
||||
|
||||
Result<int> CreateSocket(const std::string& name, int type, bool passcred, mode_t perm, uid_t uid,
|
||||
gid_t gid, const std::string& socketcon);
|
||||
|
||||
|
|
Loading…
Reference in New Issue