init: Create different file descriptors for SIGCHLD and SIGTERM
This change will allow a later CL to wait for SIGCHLD without discarding
the SIGTERM information.
Bug: 308687042
Change-Id: I5b9ab4562060455573cd816cc48bf90576b39ab9
Signed-off-by: Bart Van Assche <bvanassche@google.com>
diff --git a/init/init.cpp b/init/init.cpp
index 19f34da..68701aa 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -108,6 +108,7 @@
using android::base::StringPrintf;
using android::base::Timer;
using android::base::Trim;
+using android::base::unique_fd;
using android::fs_mgr::AvbHandle;
using android::snapshot::SnapshotManager;
@@ -116,7 +117,8 @@
static int property_triggers_enabled = 0;
-static int signal_fd = -1;
+static int sigchld_fd = -1;
+static int sigterm_fd = -1;
static int property_fd = -1;
struct PendingControlMessage {
@@ -713,8 +715,9 @@
HandlePowerctlMessage("shutdown,container");
}
-static void HandleSignalFd() {
+static void HandleSignalFd(int signal) {
signalfd_siginfo siginfo;
+ const int signal_fd = signal == SIGCHLD ? sigchld_fd : sigterm_fd;
ssize_t bytes_read = TEMP_FAILURE_RETRY(read(signal_fd, &siginfo, sizeof(siginfo)));
if (bytes_read != sizeof(siginfo)) {
PLOG(ERROR) << "Failed to read siginfo from signal_fd";
@@ -748,6 +751,24 @@
}
}
+static Result<int> CreateAndRegisterSignalFd(Epoll* epoll, int signal) {
+ sigset_t mask;
+ sigemptyset(&mask);
+ sigaddset(&mask, signal);
+ unique_fd signal_fd(signalfd(-1, &mask, SFD_CLOEXEC));
+ if (signal_fd == -1) {
+ return ErrnoError() << "failed to create signalfd for signal " << signal;
+ }
+
+ auto result = epoll->RegisterHandler(
+ signal_fd.get(), [signal]() { HandleSignalFd(signal); }, EPOLLIN | EPOLLPRI);
+ if (!result.ok()) {
+ return result.error();
+ }
+
+ return signal_fd.release();
+}
+
static void InstallSignalFdHandler(Epoll* epoll) {
// Applying SA_NOCLDSTOP to a defaulted SIGCHLD handler prevents the signalfd from receiving
// SIGCHLD when a child process stops or continues (b/77867680#comment9).
@@ -774,14 +795,18 @@
LOG(FATAL) << "Failed to register a fork handler: " << strerror(result);
}
- signal_fd = signalfd(-1, &mask, SFD_CLOEXEC);
- if (signal_fd == -1) {
- PLOG(FATAL) << "failed to create signalfd";
+ Result<int> cs_result = CreateAndRegisterSignalFd(epoll, SIGCHLD);
+ if (!cs_result.ok()) {
+ PLOG(FATAL) << cs_result.error();
}
+ sigchld_fd = cs_result.value();
- constexpr int flags = EPOLLIN | EPOLLPRI;
- if (auto result = epoll->RegisterHandler(signal_fd, HandleSignalFd, flags); !result.ok()) {
- LOG(FATAL) << result.error();
+ if (sigismember(&mask, SIGTERM)) {
+ Result<int> cs_result = CreateAndRegisterSignalFd(epoll, SIGTERM);
+ if (!cs_result.ok()) {
+ PLOG(FATAL) << cs_result.error();
+ }
+ sigterm_fd = cs_result.value();
}
}