Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d0553548 authored by Nikita Ioffe's avatar Nikita Ioffe
Browse files

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
parent acf0bebc
Loading
Loading
Loading
Loading
+15 −10
Original line number Original line Diff line number Diff line
@@ -838,20 +838,25 @@ static Result<void> DoUserspaceReboot() {
}
}


static void UserspaceRebootWatchdogThread() {
static void UserspaceRebootWatchdogThread() {
    if (!WaitForProperty("sys.init.userspace_reboot.in_progress", "1", 20s)) {
    auto started_timeout = GetMillisProperty("init.userspace_reboot.started.timeoutmillis", 10s);
        // TODO(b/135984674): should we reboot instead?
    if (!WaitForProperty("sys.init.userspace_reboot.in_progress", "1", started_timeout)) {
        LOG(WARNING) << "Userspace reboot didn't start in 20 seconds. Stopping watchdog";
        LOG(ERROR) << "Userspace reboot didn't start in " << started_timeout.count()
        return;
                   << "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";
    LOG(INFO) << "Starting userspace reboot watchdog";
    auto timeout = GetMillisProperty("init.userspace_reboot.watchdog.timeoutmillis", 5min);
    auto watchdog_timeout = GetMillisProperty("init.userspace_reboot.watchdog.timeoutmillis", 5min);
    LOG(INFO) << "UserspaceRebootWatchdog timeout: " << timeout.count() << "ms";
    LOG(INFO) << "UserspaceRebootWatchdog timeout: " << watchdog_timeout.count() << "ms";
    if (!WaitForProperty("sys.boot_completed", "1", timeout)) {
    if (!WaitForProperty("sys.boot_completed", "1", watchdog_timeout)) {
        LOG(ERROR) << "Failed to boot in " << timeout.count() << "ms. Switching to full reboot";
        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.
        // 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.
        // Since init might be wedged, don't try to write reboot reason into a persistent property.
        PersistRebootReason("userspace_failed,watchdog_triggered", false);
        PersistRebootReason("userspace_failed,watchdog_triggered,failed_to_boot", false);
        RebootSystem(ANDROID_RB_RESTART2, "userspace_failed,watchdog_triggered");
        RebootSystem(ANDROID_RB_RESTART2, "userspace_failed,watchdog_triggered,failed_to_boot");
    }
    }
    LOG(INFO) << "Device booted, stopping userspace reboot watchdog";
    LOG(INFO) << "Device booted, stopping userspace reboot watchdog";
}
}