From d485bbbb5117e58a0913c2c667647fa157dd7da3 Mon Sep 17 00:00:00 2001 From: Nikita Ioffe Date: Wed, 26 Feb 2020 15:18:56 +0000 Subject: [PATCH] If userspace reboot watchdog triggers, don't store reason in persistent property If init is wedged, then the write will never succeed and reboot won't happen. Also, in case of normal reboot, move call to PersistRebootReason to the top of DoReboot() function, to make sure we persist it even if /data is not mounted. Test: builds Test: adb shell svc power reboot userspace Test: atest CtsUserspaceRebootHostSideTestCases Bug: 148767783 Change-Id: I4ae40e1f6fdc41cc0bcae57020fa3d3385dda1b4 --- init/reboot.cpp | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/init/reboot.cpp b/init/reboot.cpp index f7cc36e14..f7bdf16ef 100644 --- a/init/reboot.cpp +++ b/init/reboot.cpp @@ -96,8 +96,10 @@ static std::vector GetDebuggingServices(bool only_post_data) REQUIRES( return ret; } -static void PersistRebootReason(const char* reason) { - SetProperty(LAST_REBOOT_REASON_PROPERTY, reason); +static void PersistRebootReason(const char* reason, bool write_to_property) { + if (write_to_property) { + SetProperty(LAST_REBOOT_REASON_PROPERTY, reason); + } WriteStringToFile(reason, LAST_REBOOT_REASON_FILE); } @@ -535,14 +537,6 @@ static void DoReboot(unsigned int cmd, const std::string& reason, const std::str Timer t; LOG(INFO) << "Reboot start, reason: " << reason << ", reboot_target: " << reboot_target; - // If /data isn't mounted then we can skip the extra reboot steps below, since we don't need to - // worry about unmounting it. - if (!IsDataMounted()) { - sync(); - RebootSystem(cmd, reboot_target); - abort(); - } - // Ensure last reboot reason is reduced to canonical // alias reported in bootloader or system boot reason. size_t skip = 0; @@ -552,9 +546,17 @@ static void DoReboot(unsigned int cmd, const std::string& reason, const std::str reasons[1] == "hard" || reasons[1] == "warm")) { skip = strlen("reboot,"); } - PersistRebootReason(reason.c_str() + skip); + PersistRebootReason(reason.c_str() + skip, true); sync(); + // If /data isn't mounted then we can skip the extra reboot steps below, since we don't need to + // worry about unmounting it. + if (!IsDataMounted()) { + sync(); + RebootSystem(cmd, reboot_target); + abort(); + } + bool is_thermal_shutdown = cmd == ANDROID_RB_THERMOFF; auto shutdown_timeout = 0ms; @@ -836,7 +838,8 @@ static void UserspaceRebootWatchdogThread() { if (!WaitForProperty("sys.boot_completed", "1", timeout)) { LOG(ERROR) << "Failed to boot in " << 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. - PersistRebootReason("userspace_failed,watchdog_triggered"); + // Since init might be wedged, don't try to write reboot reason into a persistent property. + PersistRebootReason("userspace_failed,watchdog_triggered", false); RebootSystem(ANDROID_RB_RESTART2, "userspace_failed,watchdog_triggered"); } LOG(INFO) << "Device booted, stopping userspace reboot watchdog";