Loading init/init.cpp +50 −27 Original line number Diff line number Diff line Loading @@ -79,7 +79,7 @@ static char qemu[32]; std::string default_console = "/dev/console"; static int epoll_fd = -1; static int sigterm_signal_fd = -1; static int signal_fd = -1; static std::unique_ptr<Timer> waiting_for_prop(nullptr); static std::string wait_prop_name; Loading Loading @@ -492,14 +492,7 @@ static void InstallRebootSignalHandlers() { sigaction(SIGTRAP, &action, nullptr); } static void HandleSigtermSignal() { signalfd_siginfo siginfo; ssize_t bytes_read = TEMP_FAILURE_RETRY(read(sigterm_signal_fd, &siginfo, sizeof(siginfo))); if (bytes_read != sizeof(siginfo)) { PLOG(ERROR) << "Failed to read siginfo from sigterm_signal_fd"; return; } static void HandleSigtermSignal(const signalfd_siginfo& siginfo) { if (siginfo.ssi_pid != 0) { // Drop any userspace SIGTERM requests. LOG(DEBUG) << "Ignoring SIGTERM from pid " << siginfo.ssi_pid; Loading @@ -509,37 +502,73 @@ static void HandleSigtermSignal() { HandlePowerctlMessage("shutdown,container"); } static void UnblockSigterm() { static void HandleSignalFd() { signalfd_siginfo siginfo; 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"; return; } switch (siginfo.ssi_signo) { case SIGCHLD: ReapAnyOutstandingChildren(); break; case SIGTERM: HandleSigtermSignal(siginfo); break; default: PLOG(ERROR) << "signal_fd: received unexpected signal " << siginfo.ssi_signo; break; } } static void UnblockSignals() { const struct sigaction act { .sa_handler = SIG_DFL }; sigaction(SIGCHLD, &act, nullptr); sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGCHLD); sigaddset(&mask, SIGTERM); if (sigprocmask(SIG_UNBLOCK, &mask, nullptr) == -1) { PLOG(FATAL) << "failed to unblock SIGTERM for PID " << getpid(); PLOG(FATAL) << "failed to unblock signals for PID " << getpid(); } } static void InstallSigtermHandler() { static void InstallSignalFdHandler() { // Applying SA_NOCLDSTOP to a defaulted SIGCHLD handler prevents the signalfd from receiving // SIGCHLD when a child process stops or continues (b/77867680#comment9). const struct sigaction act { .sa_handler = SIG_DFL, .sa_flags = SA_NOCLDSTOP }; sigaction(SIGCHLD, &act, nullptr); sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGCHLD); if (!IsRebootCapable()) { // If init does not have the CAP_SYS_BOOT capability, it is running in a container. // In that case, receiving SIGTERM will cause the system to shut down. sigaddset(&mask, SIGTERM); } if (sigprocmask(SIG_BLOCK, &mask, nullptr) == -1) { PLOG(FATAL) << "failed to block SIGTERM"; PLOG(FATAL) << "failed to block signals"; } // Register a handler to unblock SIGTERM in the child processes. const int result = pthread_atfork(nullptr, nullptr, &UnblockSigterm); // Register a handler to unblock signals in the child processes. const int result = pthread_atfork(nullptr, nullptr, &UnblockSignals); if (result != 0) { LOG(FATAL) << "Failed to register a fork handler: " << strerror(result); } sigterm_signal_fd = signalfd(-1, &mask, SFD_CLOEXEC); if (sigterm_signal_fd == -1) { PLOG(FATAL) << "failed to create signalfd for SIGTERM"; signal_fd = signalfd(-1, &mask, SFD_CLOEXEC); if (signal_fd == -1) { PLOG(FATAL) << "failed to create signalfd"; } register_epoll_handler(sigterm_signal_fd, HandleSigtermSignal); register_epoll_handler(signal_fd, HandleSignalFd); } int main(int argc, char** argv) { Loading Loading @@ -682,13 +711,7 @@ int main(int argc, char** argv) { PLOG(FATAL) << "epoll_create1 failed"; } sigchld_handler_init(); if (!IsRebootCapable()) { // If init does not have the CAP_SYS_BOOT capability, it is running in a container. // In that case, receiving SIGTERM will cause the system to shut down. InstallSigtermHandler(); } InstallSignalFdHandler(); property_load_boot_defaults(); export_oem_lock_status(); Loading init/sigchld_handler.cpp +0 −39 Original line number Diff line number Diff line Loading @@ -39,9 +39,6 @@ using android::base::make_scope_guard; namespace android { namespace init { static int signal_write_fd = -1; static int signal_read_fd = -1; static bool ReapOneProcess() { siginfo_t siginfo = {}; // This returns a zombie pid or informs us that there are no zombies left to be reaped. Loading Loading @@ -102,46 +99,10 @@ static bool ReapOneProcess() { return true; } static void handle_signal() { // Clear outstanding requests. char buf[32]; read(signal_read_fd, buf, sizeof(buf)); ReapAnyOutstandingChildren(); } static void SIGCHLD_handler(int) { if (TEMP_FAILURE_RETRY(write(signal_write_fd, "1", 1)) == -1) { PLOG(ERROR) << "write(signal_write_fd) failed"; } } void ReapAnyOutstandingChildren() { while (ReapOneProcess()) { } } void sigchld_handler_init() { // Create a signalling mechanism for SIGCHLD. int s[2]; if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, s) == -1) { PLOG(FATAL) << "socketpair failed in sigchld_handler_init"; } signal_write_fd = s[0]; signal_read_fd = s[1]; // Write to signal_write_fd if we catch SIGCHLD. struct sigaction act; memset(&act, 0, sizeof(act)); act.sa_handler = SIGCHLD_handler; act.sa_flags = SA_NOCLDSTOP; sigaction(SIGCHLD, &act, 0); ReapAnyOutstandingChildren(); register_epoll_handler(signal_read_fd, handle_signal); } } // namespace init } // namespace android init/sigchld_handler.h +0 −2 Original line number Diff line number Diff line Loading @@ -22,8 +22,6 @@ namespace init { void ReapAnyOutstandingChildren(); void sigchld_handler_init(void); } // namespace init } // namespace android Loading Loading
init/init.cpp +50 −27 Original line number Diff line number Diff line Loading @@ -79,7 +79,7 @@ static char qemu[32]; std::string default_console = "/dev/console"; static int epoll_fd = -1; static int sigterm_signal_fd = -1; static int signal_fd = -1; static std::unique_ptr<Timer> waiting_for_prop(nullptr); static std::string wait_prop_name; Loading Loading @@ -492,14 +492,7 @@ static void InstallRebootSignalHandlers() { sigaction(SIGTRAP, &action, nullptr); } static void HandleSigtermSignal() { signalfd_siginfo siginfo; ssize_t bytes_read = TEMP_FAILURE_RETRY(read(sigterm_signal_fd, &siginfo, sizeof(siginfo))); if (bytes_read != sizeof(siginfo)) { PLOG(ERROR) << "Failed to read siginfo from sigterm_signal_fd"; return; } static void HandleSigtermSignal(const signalfd_siginfo& siginfo) { if (siginfo.ssi_pid != 0) { // Drop any userspace SIGTERM requests. LOG(DEBUG) << "Ignoring SIGTERM from pid " << siginfo.ssi_pid; Loading @@ -509,37 +502,73 @@ static void HandleSigtermSignal() { HandlePowerctlMessage("shutdown,container"); } static void UnblockSigterm() { static void HandleSignalFd() { signalfd_siginfo siginfo; 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"; return; } switch (siginfo.ssi_signo) { case SIGCHLD: ReapAnyOutstandingChildren(); break; case SIGTERM: HandleSigtermSignal(siginfo); break; default: PLOG(ERROR) << "signal_fd: received unexpected signal " << siginfo.ssi_signo; break; } } static void UnblockSignals() { const struct sigaction act { .sa_handler = SIG_DFL }; sigaction(SIGCHLD, &act, nullptr); sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGCHLD); sigaddset(&mask, SIGTERM); if (sigprocmask(SIG_UNBLOCK, &mask, nullptr) == -1) { PLOG(FATAL) << "failed to unblock SIGTERM for PID " << getpid(); PLOG(FATAL) << "failed to unblock signals for PID " << getpid(); } } static void InstallSigtermHandler() { static void InstallSignalFdHandler() { // Applying SA_NOCLDSTOP to a defaulted SIGCHLD handler prevents the signalfd from receiving // SIGCHLD when a child process stops or continues (b/77867680#comment9). const struct sigaction act { .sa_handler = SIG_DFL, .sa_flags = SA_NOCLDSTOP }; sigaction(SIGCHLD, &act, nullptr); sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGCHLD); if (!IsRebootCapable()) { // If init does not have the CAP_SYS_BOOT capability, it is running in a container. // In that case, receiving SIGTERM will cause the system to shut down. sigaddset(&mask, SIGTERM); } if (sigprocmask(SIG_BLOCK, &mask, nullptr) == -1) { PLOG(FATAL) << "failed to block SIGTERM"; PLOG(FATAL) << "failed to block signals"; } // Register a handler to unblock SIGTERM in the child processes. const int result = pthread_atfork(nullptr, nullptr, &UnblockSigterm); // Register a handler to unblock signals in the child processes. const int result = pthread_atfork(nullptr, nullptr, &UnblockSignals); if (result != 0) { LOG(FATAL) << "Failed to register a fork handler: " << strerror(result); } sigterm_signal_fd = signalfd(-1, &mask, SFD_CLOEXEC); if (sigterm_signal_fd == -1) { PLOG(FATAL) << "failed to create signalfd for SIGTERM"; signal_fd = signalfd(-1, &mask, SFD_CLOEXEC); if (signal_fd == -1) { PLOG(FATAL) << "failed to create signalfd"; } register_epoll_handler(sigterm_signal_fd, HandleSigtermSignal); register_epoll_handler(signal_fd, HandleSignalFd); } int main(int argc, char** argv) { Loading Loading @@ -682,13 +711,7 @@ int main(int argc, char** argv) { PLOG(FATAL) << "epoll_create1 failed"; } sigchld_handler_init(); if (!IsRebootCapable()) { // If init does not have the CAP_SYS_BOOT capability, it is running in a container. // In that case, receiving SIGTERM will cause the system to shut down. InstallSigtermHandler(); } InstallSignalFdHandler(); property_load_boot_defaults(); export_oem_lock_status(); Loading
init/sigchld_handler.cpp +0 −39 Original line number Diff line number Diff line Loading @@ -39,9 +39,6 @@ using android::base::make_scope_guard; namespace android { namespace init { static int signal_write_fd = -1; static int signal_read_fd = -1; static bool ReapOneProcess() { siginfo_t siginfo = {}; // This returns a zombie pid or informs us that there are no zombies left to be reaped. Loading Loading @@ -102,46 +99,10 @@ static bool ReapOneProcess() { return true; } static void handle_signal() { // Clear outstanding requests. char buf[32]; read(signal_read_fd, buf, sizeof(buf)); ReapAnyOutstandingChildren(); } static void SIGCHLD_handler(int) { if (TEMP_FAILURE_RETRY(write(signal_write_fd, "1", 1)) == -1) { PLOG(ERROR) << "write(signal_write_fd) failed"; } } void ReapAnyOutstandingChildren() { while (ReapOneProcess()) { } } void sigchld_handler_init() { // Create a signalling mechanism for SIGCHLD. int s[2]; if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, s) == -1) { PLOG(FATAL) << "socketpair failed in sigchld_handler_init"; } signal_write_fd = s[0]; signal_read_fd = s[1]; // Write to signal_write_fd if we catch SIGCHLD. struct sigaction act; memset(&act, 0, sizeof(act)); act.sa_handler = SIGCHLD_handler; act.sa_flags = SA_NOCLDSTOP; sigaction(SIGCHLD, &act, 0); ReapAnyOutstandingChildren(); register_epoll_handler(signal_read_fd, handle_signal); } } // namespace init } // namespace android
init/sigchld_handler.h +0 −2 Original line number Diff line number Diff line Loading @@ -22,8 +22,6 @@ namespace init { void ReapAnyOutstandingChildren(); void sigchld_handler_init(void); } // namespace init } // namespace android Loading