Clean up userspace-reboot
The feature was deprecated last year.
Bug: 292469129
Test: atest CtsInitTestCases
Change-Id: I826502770ab3fa566be57a33829f1103efa893fb
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 150f8f4..66ee977 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -87,16 +87,6 @@
static const std::set<std::string> kDebuggingServices{"tombstoned", "logd", "adbd", "console"};
-static std::set<std::string> GetPostDataDebuggingServices() {
- std::set<std::string> ret;
- for (const auto& s : ServiceList::GetInstance()) {
- if (kDebuggingServices.count(s->name()) && s->is_post_data()) {
- ret.insert(s->name());
- }
- }
- return ret;
-}
-
static void PersistRebootReason(const char* reason, bool write_to_property) {
if (write_to_property) {
SetProperty(LAST_REBOOT_REASON_PROPERTY, reason);
@@ -810,196 +800,6 @@
}
}
-static void LeaveShutdown() {
- LOG(INFO) << "Leaving shutdown mode";
- shutting_down = false;
- StartSendingMessages();
-}
-
-static std::chrono::milliseconds GetMillisProperty(const std::string& name,
- std::chrono::milliseconds default_value) {
- auto value = GetUintProperty(name, static_cast<uint64_t>(default_value.count()));
- return std::chrono::milliseconds(std::move(value));
-}
-
-static Result<void> DoUserspaceReboot() {
- LOG(INFO) << "Userspace reboot initiated";
- // An ugly way to pass a more precise reason on why fallback to hard reboot was triggered.
- std::string sub_reason = "";
- auto guard = android::base::make_scope_guard([&sub_reason] {
- // Leave shutdown so that we can handle a full reboot.
- LeaveShutdown();
- trigger_shutdown("reboot,userspace_failed,shutdown_aborted," + sub_reason);
- });
- // Triggering userspace-reboot-requested will result in a bunch of setprop
- // actions. We should make sure, that all of them are propagated before
- // proceeding with userspace reboot. Synchronously setting sys.init.userspace_reboot.in_progress
- // property is not perfect, but it should do the trick.
- if (!android::sysprop::InitProperties::userspace_reboot_in_progress(true)) {
- sub_reason = "setprop";
- return Error() << "Failed to set sys.init.userspace_reboot.in_progress property";
- }
- EnterShutdown();
- if (!SetProperty("sys.powerctl", "")) {
- sub_reason = "resetprop";
- return Error() << "Failed to reset sys.powerctl property";
- }
- std::set<std::string> stop_first;
- // Remember the services that were enabled. We will need to manually enable them again otherwise
- // triggers like class_start won't restart them.
- std::set<std::string> were_enabled;
- for (const auto& s : ServiceList::GetInstance().services_in_shutdown_order()) {
- if (s->is_post_data() && !kDebuggingServices.count(s->name())) {
- stop_first.insert(s->name());
- }
- // TODO(ioffe): we should also filter out temporary services here.
- if (s->is_post_data() && s->IsEnabled()) {
- were_enabled.insert(s->name());
- }
- }
- {
- Timer sync_timer;
- LOG(INFO) << "sync() before terminating services...";
- sync();
- LOG(INFO) << "sync() took " << sync_timer;
- }
- auto sigterm_timeout = GetMillisProperty("init.userspace_reboot.sigterm.timeoutmillis", 5s);
- auto sigkill_timeout = GetMillisProperty("init.userspace_reboot.sigkill.timeoutmillis", 10s);
- LOG(INFO) << "Timeout to terminate services: " << sigterm_timeout.count() << "ms "
- << "Timeout to kill services: " << sigkill_timeout.count() << "ms";
- std::string services_file_name = "/metadata/userspacereboot/services.txt";
- const int flags = O_RDWR | O_CREAT | O_SYNC | O_APPEND | O_CLOEXEC;
- StopServicesAndLogViolations(stop_first, sigterm_timeout, true /* SIGTERM */);
- if (int r = StopServicesAndLogViolations(stop_first, sigkill_timeout, false /* SIGKILL */);
- r > 0) {
- auto fd = unique_fd(TEMP_FAILURE_RETRY(open(services_file_name.c_str(), flags, 0666)));
- android::base::WriteStringToFd("Post-data services still running: \n", fd);
- for (const auto& s : ServiceList::GetInstance()) {
- if (s->IsRunning() && stop_first.count(s->name())) {
- android::base::WriteStringToFd(s->name() + "\n", fd);
- }
- }
- sub_reason = "sigkill";
- return Error() << r << " post-data services are still running";
- }
- if (auto result = KillZramBackingDevice(); !result.ok()) {
- sub_reason = "zram";
- return result;
- }
- if (auto result = CallVdc("volume", "reset"); !result.ok()) {
- sub_reason = "vold_reset";
- return result;
- }
- const auto& debugging_services = GetPostDataDebuggingServices();
- if (int r = StopServicesAndLogViolations(debugging_services, sigkill_timeout,
- false /* SIGKILL */);
- r > 0) {
- auto fd = unique_fd(TEMP_FAILURE_RETRY(open(services_file_name.c_str(), flags, 0666)));
- android::base::WriteStringToFd("Debugging services still running: \n", fd);
- for (const auto& s : ServiceList::GetInstance()) {
- if (s->IsRunning() && debugging_services.count(s->name())) {
- android::base::WriteStringToFd(s->name() + "\n", fd);
- }
- }
- sub_reason = "sigkill_debug";
- return Error() << r << " debugging services are still running";
- }
- {
- Timer sync_timer;
- LOG(INFO) << "sync() after stopping services...";
- sync();
- LOG(INFO) << "sync() took " << sync_timer;
- }
- if (auto result = UnmountAllApexes(); !result.ok()) {
- sub_reason = "apex";
- return result;
- }
- if (!SwitchToMountNamespaceIfNeeded(NS_BOOTSTRAP).ok()) {
- sub_reason = "ns_switch";
- return Error() << "Failed to switch to bootstrap namespace";
- }
- ActionManager::GetInstance().RemoveActionIf([](const auto& action) -> bool {
- if (action->IsFromApex()) {
- std::string trigger_name = action->BuildTriggersString();
- LOG(INFO) << "Removing action (" << trigger_name << ") from (" << action->filename()
- << ":" << action->line() << ")";
- return true;
- }
- return false;
- });
- // Remove services that were defined in an APEX
- ServiceList::GetInstance().RemoveServiceIf([](const std::unique_ptr<Service>& s) -> bool {
- if (s->is_from_apex()) {
- LOG(INFO) << "Removing service '" << s->name() << "' because it's defined in an APEX";
- return true;
- }
- return false;
- });
- // Re-enable services
- for (const auto& s : ServiceList::GetInstance()) {
- if (were_enabled.count(s->name())) {
- LOG(INFO) << "Re-enabling service '" << s->name() << "'";
- s->Enable();
- }
- }
- ServiceList::GetInstance().ResetState();
- LeaveShutdown();
- ActionManager::GetInstance().QueueEventTrigger("userspace-reboot-resume");
- guard.Disable(); // Go on with userspace reboot.
- return {};
-}
-
-static void UserspaceRebootWatchdogThread() {
- auto started_timeout = GetMillisProperty("init.userspace_reboot.started.timeoutmillis", 10s);
- if (!WaitForProperty("sys.init.userspace_reboot.in_progress", "1", started_timeout)) {
- LOG(ERROR) << "Userspace reboot didn't start in " << started_timeout.count()
- << "ms. Switching to full reboot";
- // Init might be wedged, don't try to write reboot reason into a persistent property and do
- // a dirty reboot.
- PersistRebootReason("userspace_failed,watchdog_triggered,failed_to_start", false);
- RebootSystem(ANDROID_RB_RESTART2, "userspace_failed,watchdog_triggered,failed_to_start");
- }
- LOG(INFO) << "Starting userspace reboot watchdog";
- auto watchdog_timeout = GetMillisProperty("init.userspace_reboot.watchdog.timeoutmillis", 5min);
- LOG(INFO) << "UserspaceRebootWatchdog timeout: " << watchdog_timeout.count() << "ms";
- if (!WaitForProperty("sys.boot_completed", "1", watchdog_timeout)) {
- LOG(ERROR) << "Failed to boot in " << watchdog_timeout.count()
- << "ms. Switching to full reboot";
- // In this case device is in a boot loop. Only way to recover is to do dirty reboot.
- // Since init might be wedged, don't try to write reboot reason into a persistent property.
- PersistRebootReason("userspace_failed,watchdog_triggered,failed_to_boot", false);
- RebootSystem(ANDROID_RB_RESTART2, "userspace_failed,watchdog_triggered,failed_to_boot");
- }
- LOG(INFO) << "Device booted, stopping userspace reboot watchdog";
-}
-
-static void HandleUserspaceReboot() {
- if (!android::sysprop::InitProperties::is_userspace_reboot_supported().value_or(false)) {
- LOG(ERROR) << "Attempted a userspace reboot on a device that doesn't support it";
- return;
- }
- // Spinnig up a separate thread will fail the setns call later in the boot sequence.
- // Fork a new process to monitor userspace reboot while we are investigating a better solution.
- pid_t pid = fork();
- if (pid < 0) {
- PLOG(ERROR) << "Failed to fork process for userspace reboot watchdog. Switching to full "
- << "reboot";
- trigger_shutdown("reboot,userspace_failed,watchdog_fork");
- return;
- }
- if (pid == 0) {
- // Child
- UserspaceRebootWatchdogThread();
- _exit(EXIT_SUCCESS);
- }
- LOG(INFO) << "Clearing queue and starting userspace-reboot-requested trigger";
- auto& am = ActionManager::GetInstance();
- am.ClearQueue();
- am.QueueEventTrigger("userspace-reboot-requested");
- auto handler = [](const BuiltinArguments&) { return DoUserspaceReboot(); };
- am.QueueBuiltinAction(handler, "userspace-reboot");
-}
-
/**
* Check if "command" field is set in bootloader message.
*
@@ -1030,7 +830,6 @@
std::string reboot_target = "";
bool run_fsck = false;
bool command_invalid = false;
- bool userspace_reboot = false;
if (cmd_params[0] == "shutdown") {
cmd = ANDROID_RB_POWEROFF;
@@ -1051,8 +850,8 @@
if (cmd_params.size() >= 2) {
reboot_target = cmd_params[1];
if (reboot_target == "userspace") {
- LOG(INFO) << "Userspace reboot requested";
- userspace_reboot = true;
+ LOG(ERROR) << "Userspace reboot is deprecated.";
+ return;
}
// adb reboot fastboot should boot into bootloader for devices not
// supporting logical partitions.
@@ -1130,11 +929,6 @@
// messages, etc) from properties during reboot.
StopSendingMessages();
- if (userspace_reboot) {
- HandleUserspaceReboot();
- return;
- }
-
LOG(INFO) << "Clear action queue and start shutdown trigger";
ActionManager::GetInstance().ClearQueue();
// Queue shutdown trigger first