From 6236af3d0c6422bbc88aa883ebdb717352d69ad4 Mon Sep 17 00:00:00 2001 From: Nikita Ioffe Date: Sat, 11 Apr 2020 01:55:24 +0100 Subject: [PATCH] Fallback to hard reboot if userspace reboot hasn't started in time Similarly to other recovery mechanisms, timeout is controlled by a read-only property that can be configured per-device. Test: adb root Test: adb shell setprop init.userspace_reboot.started.timeoutmillis 2 Test: adb reboot userspace Bug: 152803929 Change-Id: Id70710b46da798945ac5422ef7d69265911ea5ef Merged-In: Id70710b46da798945ac5422ef7d69265911ea5ef (cherry picked from commit d05535485f7a818cda3bfa4b61bfd071be56b36f) --- init/reboot.cpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/init/reboot.cpp b/init/reboot.cpp index d2dc6d350..2f9166325 100644 --- a/init/reboot.cpp +++ b/init/reboot.cpp @@ -838,20 +838,25 @@ static Result DoUserspaceReboot() { } static void UserspaceRebootWatchdogThread() { - if (!WaitForProperty("sys.init.userspace_reboot.in_progress", "1", 20s)) { - // TODO(b/135984674): should we reboot instead? - LOG(WARNING) << "Userspace reboot didn't start in 20 seconds. Stopping watchdog"; - return; + 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 timeout = GetMillisProperty("init.userspace_reboot.watchdog.timeoutmillis", 5min); - LOG(INFO) << "UserspaceRebootWatchdog timeout: " << timeout.count() << "ms"; - if (!WaitForProperty("sys.boot_completed", "1", timeout)) { - LOG(ERROR) << "Failed to boot in " << timeout.count() << "ms. Switching to full reboot"; + 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", false); - RebootSystem(ANDROID_RB_RESTART2, "userspace_failed,watchdog_triggered"); + 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"; }