init: replace panic() with LOG(FATAL)
Test: boot bullhead
Test: Introduce LOG(FATAL) at various points of init and ensure that
it reboots to the bootloader successfully
Test: Introduce LOG(FATAL) during DoReboot() and ensure that it reboots
instead of recursing infinitely
Test: Ensure that fatal signals reboot to bootloader
Change-Id: I409005b6fab379df2d635e3e33d2df48a1a97df3
diff --git a/init/init.cpp b/init/init.cpp
index c65d846..d0afac1 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -34,6 +34,7 @@
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/strings.h>
+#include <cutils/android_reboot.h>
#include <keyutils.h>
#include <libavb/libavb.h>
#include <private/android_filesystem_config.h>
@@ -252,8 +253,7 @@
// because any build that slow isn't likely to boot at all, and we'd
// rather any test lab devices fail back to the bootloader.
if (wait_for_file(COLDBOOT_DONE, 60s) < 0) {
- LOG(ERROR) << "Timed out waiting for " COLDBOOT_DONE;
- panic();
+ LOG(FATAL) << "Timed out waiting for " COLDBOOT_DONE;
}
property_set("ro.boottime.init.cold_boot_wait", std::to_string(t.duration().count()));
@@ -367,8 +367,7 @@
static void global_seccomp() {
import_kernel_cmdline(false, [](const std::string& key, const std::string& value, bool in_qemu) {
if (key == "androidboot.seccomp" && value == "global" && !set_global_seccomp_filter()) {
- LOG(ERROR) << "Failed to globally enable seccomp!";
- panic();
+ LOG(FATAL) << "Failed to globally enable seccomp!";
}
});
}
@@ -398,8 +397,11 @@
memset(&action, 0, sizeof(action));
sigfillset(&action.sa_mask);
action.sa_handler = [](int) {
- // panic() reboots to bootloader
- panic();
+ // Calling DoReboot() or LOG(FATAL) is not a good option as this is a signal handler.
+ // RebootSystem uses syscall() which isn't actually async-signal-safe, but our only option
+ // and probably good enough given this is already an error case and only enabled for
+ // development builds.
+ RebootSystem(ANDROID_RB_RESTART2, "bootloader");
};
action.sa_flags = SA_RESTART;
sigaction(SIGABRT, &action, nullptr);
@@ -468,8 +470,7 @@
LOG(INFO) << "init first stage started!";
if (!DoFirstStageMount()) {
- LOG(ERROR) << "Failed to mount required partitions early ...";
- panic();
+ LOG(FATAL) << "Failed to mount required partitions early ...";
}
SetInitAvbVersionInRecovery();
@@ -484,8 +485,7 @@
// We're in the kernel domain, so re-exec init to transition to the init domain now
// that the SELinux policy has been loaded.
if (selinux_android_restorecon("/init", 0) == -1) {
- PLOG(ERROR) << "restorecon failed of /init failed";
- panic();
+ PLOG(FATAL) << "restorecon failed of /init failed";
}
setenv("INIT_SECOND_STAGE", "true", 1);
@@ -500,8 +500,7 @@
// execv() only returns if an error happened, in which case we
// panic and never fall through this conditional.
- PLOG(ERROR) << "execv(\"" << path << "\") failed";
- panic();
+ PLOG(FATAL) << "execv(\"" << path << "\") failed";
}
// At this point we're in the second stage of init.