Merge changes I5e259fdd,I5b9ab456 into main
* changes:
init: Make WaitToBeReaped() wait less long
init: Create different file descriptors for SIGCHLD and SIGTERM
diff --git a/init/init.cpp b/init/init.cpp
index 19f34da..0439d22 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;
+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,19 @@
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();
+ Service::SetSigchldFd(sigchld_fd);
- 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();
}
}
diff --git a/init/init.h b/init/init.h
index 9c7e918..b781167 100644
--- a/init/init.h
+++ b/init/init.h
@@ -28,6 +28,8 @@
namespace android {
namespace init {
+extern int sigchld_fd;
+
Parser CreateParser(ActionManager& action_manager, ServiceList& service_list);
Parser CreateApexConfigParser(ActionManager& action_manager, ServiceList& service_list);
diff --git a/init/reboot.cpp b/init/reboot.cpp
index 3351c4c..5757922 100644
--- a/init/reboot.cpp
+++ b/init/reboot.cpp
@@ -563,7 +563,7 @@
}
}
if (timeout > 0ms) {
- WaitToBeReaped(pids, timeout);
+ WaitToBeReaped(sigchld_fd, pids, timeout);
} else {
// Even if we don't to wait for services to stop, we still optimistically reap zombies.
ReapAnyOutstandingChildren();
diff --git a/init/service.cpp b/init/service.cpp
index 2087452..311a132 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -136,6 +136,7 @@
unsigned long Service::next_start_order_ = 1;
bool Service::is_exec_service_running_ = false;
+int Service::sigchld_fd_ = -1;
Service::Service(const std::string& name, Subcontext* subcontext_for_restart_commands,
const std::string& filename, const std::vector<std::string>& args)
diff --git a/init/service.h b/init/service.h
index 35521b2..13c8b5f 100644
--- a/init/service.h
+++ b/init/service.h
@@ -156,6 +156,7 @@
const Subcontext* subcontext() const { return subcontext_; }
const std::string& filename() const { return filename_; }
void set_filename(const std::string& name) { filename_ = name; }
+ static void SetSigchldFd(int sigchld_fd) { sigchld_fd_ = sigchld_fd; }
private:
void NotifyStateChange(const std::string& new_state) const;
@@ -168,8 +169,10 @@
void RunService(const std::vector<Descriptor>& descriptors, InterprocessFifo cgroups_activated,
InterprocessFifo setsid_finished);
void SetMountNamespace();
+
static unsigned long next_start_order_;
static bool is_exec_service_running_;
+ static int sigchld_fd_;
const std::string name_;
std::set<std::string> classnames_;
diff --git a/init/sigchld_handler.cpp b/init/sigchld_handler.cpp
index 0901a96..9d4c7c8 100644
--- a/init/sigchld_handler.cpp
+++ b/init/sigchld_handler.cpp
@@ -18,6 +18,7 @@
#include <signal.h>
#include <string.h>
+#include <sys/signalfd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
@@ -31,6 +32,7 @@
#include <thread>
+#include "epoll.h"
#include "init.h"
#include "service.h"
#include "service_list.h"
@@ -121,8 +123,23 @@
}
}
-void WaitToBeReaped(const std::vector<pid_t>& pids, std::chrono::milliseconds timeout) {
+static void DiscardSiginfo(int signal_fd) {
+ signalfd_siginfo siginfo;
+ ssize_t bytes_read = TEMP_FAILURE_RETRY(read(signal_fd, &siginfo, sizeof(siginfo)));
+ if (bytes_read != sizeof(siginfo)) {
+ LOG(WARNING) << "Unexpected: " << __func__ << " read " << bytes_read << " bytes instead of "
+ << sizeof(siginfo);
+ }
+}
+
+void WaitToBeReaped(int sigchld_fd, const std::vector<pid_t>& pids,
+ std::chrono::milliseconds timeout) {
Timer t;
+ Epoll epoll;
+ // The init process passes a valid sigchld_fd argument but unit tests do not.
+ if (sigchld_fd >= 0) {
+ epoll.RegisterHandler(sigchld_fd, [sigchld_fd]() { DiscardSiginfo(sigchld_fd); });
+ }
std::vector<pid_t> alive_pids(pids.begin(), pids.end());
while (!alive_pids.empty() && t.duration() < timeout) {
pid_t pid;
@@ -135,7 +152,11 @@
if (alive_pids.empty()) {
break;
}
- std::this_thread::sleep_for(50ms);
+ if (sigchld_fd >= 0) {
+ epoll.Wait(std::max(timeout - t.duration(), 0ms));
+ } else {
+ std::this_thread::sleep_for(50ms);
+ }
}
LOG(INFO) << "Waiting for " << pids.size() << " pids to be reaped took " << t << " with "
<< alive_pids.size() << " of them still running";
diff --git a/init/sigchld_handler.h b/init/sigchld_handler.h
index fac1020..e07a7d6 100644
--- a/init/sigchld_handler.h
+++ b/init/sigchld_handler.h
@@ -25,7 +25,8 @@
void ReapAnyOutstandingChildren();
-void WaitToBeReaped(const std::vector<pid_t>& pids, std::chrono::milliseconds timeout);
+void WaitToBeReaped(int sigchld_fd, const std::vector<pid_t>& pids,
+ std::chrono::milliseconds timeout);
} // namespace init
} // namespace android