Merge "init: replace panic() with LOG(FATAL)"
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.
diff --git a/init/log.cpp b/init/log.cpp
index 1830077..391bc1f 100644
--- a/init/log.cpp
+++ b/init/log.cpp
@@ -21,17 +21,35 @@
#include <string.h>
#include <android-base/logging.h>
+#include <cutils/android_reboot.h>
#include <selinux/selinux.h>
+#include "reboot.h"
+
namespace android {
namespace init {
+static void RebootAborter(const char* abort_message) {
+ // DoReboot() does a lot to try to shutdown the system cleanly. If something happens to call
+ // LOG(FATAL) in the shutdown path, we want to catch this and immediately use the syscall to
+ // reboot instead of recursing here.
+ static bool has_aborted = false;
+ if (!has_aborted) {
+ has_aborted = true;
+ // Do not queue "shutdown" trigger since we want to shutdown immediately and it's not likely
+ // that we can even run the ActionQueue at this point.
+ DoReboot(ANDROID_RB_RESTART2, "reboot", "bootloader", false);
+ } else {
+ RebootSystem(ANDROID_RB_RESTART2, "bootloader");
+ }
+}
+
void InitKernelLogging(char* argv[]) {
// Make stdin/stdout/stderr all point to /dev/null.
int fd = open("/sys/fs/selinux/null", O_RDWR);
if (fd == -1) {
int saved_errno = errno;
- android::base::InitLogging(argv, &android::base::KernelLogger);
+ android::base::InitLogging(argv, &android::base::KernelLogger, RebootAborter);
errno = saved_errno;
PLOG(FATAL) << "Couldn't open /sys/fs/selinux/null";
}
@@ -40,7 +58,7 @@
dup2(fd, 2);
if (fd > 2) close(fd);
- android::base::InitLogging(argv, &android::base::KernelLogger);
+ android::base::InitLogging(argv, &android::base::KernelLogger, RebootAborter);
}
int selinux_klog_callback(int type, const char *fmt, ...) {
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 4d580f2..5bae4bc 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -191,8 +191,7 @@
return value == CAP_SET;
}
-static void __attribute__((noreturn))
-RebootSystem(unsigned int cmd, const std::string& rebootTarget) {
+void __attribute__((noreturn)) RebootSystem(unsigned int cmd, const std::string& rebootTarget) {
LOG(INFO) << "Reboot ending, jumping to kernel";
if (!IsRebootCapable()) {
@@ -216,7 +215,7 @@
break;
}
// In normal case, reboot should not return.
- PLOG(FATAL) << "reboot call returned";
+ PLOG(ERROR) << "reboot call returned";
abort();
}
diff --git a/init/reboot.h b/init/reboot.h
index e559540..8586556 100644
--- a/init/reboot.h
+++ b/init/reboot.h
@@ -22,6 +22,9 @@
namespace android {
namespace init {
+// This is a wrapper around the actual reboot calls. DoReboot() should be preferred in most cases.
+void __attribute__((noreturn)) RebootSystem(unsigned int cmd, const std::string& rebootTarget);
+
/* Reboot / shutdown the system.
* cmd ANDROID_RB_* as defined in android_reboot.h
* reason Reason string like "reboot", "userrequested"
diff --git a/init/security.cpp b/init/security.cpp
index f8976de..aac8f2e 100644
--- a/init/security.cpp
+++ b/init/security.cpp
@@ -25,8 +25,6 @@
#include <android-base/logging.h>
#include <android-base/unique_fd.h>
-#include "util.h"
-
using android::base::unique_fd;
namespace android {
@@ -178,8 +176,7 @@
LOG(ERROR) << "Unknown architecture";
#endif
- LOG(ERROR) << "Unable to set adequate mmap entropy value!";
- panic();
+ LOG(FATAL) << "Unable to set adequate mmap entropy value!";
return Error();
}
@@ -194,8 +191,7 @@
std::string path = KPTR_RESTRICT_PATH;
if (!SetHighestAvailableOptionValue(path, KPTR_RESTRICT_MINVALUE, KPTR_RESTRICT_MAXVALUE)) {
- LOG(ERROR) << "Unable to set adequate kptr_restrict value!";
- panic();
+ LOG(FATAL) << "Unable to set adequate kptr_restrict value!";
return Error();
}
return Success();
diff --git a/init/selinux.cpp b/init/selinux.cpp
index dd49f84..1104fb3 100644
--- a/init/selinux.cpp
+++ b/init/selinux.cpp
@@ -327,21 +327,19 @@
LOG(INFO) << "Loading SELinux policy";
if (!LoadPolicy()) {
- panic();
+ LOG(FATAL) << "Unable to load SELinux policy";
}
bool kernel_enforcing = (security_getenforce() == 1);
bool is_enforcing = IsEnforcing();
if (kernel_enforcing != is_enforcing) {
if (security_setenforce(is_enforcing)) {
- PLOG(ERROR) << "security_setenforce(%s) failed" << (is_enforcing ? "true" : "false");
- panic();
+ PLOG(FATAL) << "security_setenforce(%s) failed" << (is_enforcing ? "true" : "false");
}
}
if (auto result = WriteFile("/sys/fs/selinux/checkreqprot", "0"); !result) {
- LOG(ERROR) << "Unable to write to /sys/fs/selinux/checkreqprot: " << result.error();
- panic();
+ LOG(FATAL) << "Unable to write to /sys/fs/selinux/checkreqprot: " << result.error();
}
// init's first stage can't set properties, so pass the time to the second stage.
diff --git a/init/service.cpp b/init/service.cpp
index 1b5cc19..c201ec9 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -306,8 +306,7 @@
if ((flags_ & SVC_CRITICAL) && !(flags_ & SVC_RESTART)) {
if (now < time_crashed_ + 4min) {
if (++crash_count_ > 4) {
- LOG(ERROR) << "critical process '" << name_ << "' exited 4 times in 4 minutes";
- panic();
+ LOG(FATAL) << "critical process '" << name_ << "' exited 4 times in 4 minutes";
}
} else {
time_crashed_ = now;
diff --git a/init/util.cpp b/init/util.cpp
index fcf7ca8..9112c3f 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -345,12 +345,6 @@
return true;
}
-void panic() {
- LOG(ERROR) << "panic: rebooting to bootloader";
- // Do not queue "shutdown" trigger since we want to shutdown immediately
- DoReboot(ANDROID_RB_RESTART2, "reboot", "bootloader", false);
-}
-
static std::string init_android_dt_dir() {
// Use the standard procfs-based path by default
std::string android_dt_dir = kDefaultAndroidDtDir;
diff --git a/init/util.h b/init/util.h
index 298aa1c..2cfcf6c 100644
--- a/init/util.h
+++ b/init/util.h
@@ -55,8 +55,6 @@
bool is_dir(const char* pathname);
bool expand_props(const std::string& src, std::string* dst);
-void panic() __attribute__((__noreturn__));
-
// Returns the platform's Android DT directory as specified in the kernel cmdline.
// If the platform does not configure a custom DT path, returns the standard one (based in procfs).
const std::string& get_android_dt_dir();