Loading init/init.cpp +14 −27 Original line number Diff line number Diff line Loading @@ -117,7 +117,6 @@ namespace init { static int property_triggers_enabled = 0; int sigchld_fd = -1; static int sigterm_fd = -1; static int property_fd = -1; Loading Loading @@ -717,7 +716,7 @@ static void HandleSigtermSignal(const signalfd_siginfo& siginfo) { static void HandleSignalFd(int signal) { signalfd_siginfo siginfo; const int signal_fd = signal == SIGCHLD ? sigchld_fd : sigterm_fd; const int signal_fd = signal == SIGCHLD ? Service::GetSigchldFd() : 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"; Loading Loading @@ -751,20 +750,24 @@ static void UnblockSignals() { } } static Result<void> RegisterSignalFd(Epoll* epoll, int signal, int fd) { return epoll->RegisterHandler( fd, [signal]() { HandleSignalFd(signal); }, EPOLLIN | EPOLLPRI); } 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; if (sigprocmask(SIG_BLOCK, &mask, nullptr) == -1) { return ErrnoError() << "failed to block signal " << signal; } auto result = epoll->RegisterHandler( signal_fd.get(), [signal]() { HandleSignalFd(signal); }, EPOLLIN | EPOLLPRI); if (!result.ok()) { return result.error(); unique_fd signal_fd(signalfd(-1, &mask, SFD_CLOEXEC)); if (signal_fd.get() < 0) { return ErrnoError() << "failed to create signalfd for signal " << signal; } OR_RETURN(RegisterSignalFd(epoll, signal, signal_fd.get())); return signal_fd.release(); } Loading @@ -775,34 +778,18 @@ static void InstallSignalFdHandler(Epoll* epoll) { const struct sigaction act { .sa_flags = SA_NOCLDSTOP, .sa_handler = SIG_DFL }; 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 signals"; } // 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); } Result<int> cs_result = CreateAndRegisterSignalFd(epoll, SIGCHLD); Result<void> cs_result = RegisterSignalFd(epoll, SIGCHLD, Service::GetSigchldFd()); if (!cs_result.ok()) { PLOG(FATAL) << cs_result.error(); } sigchld_fd = cs_result.value(); Service::SetSigchldFd(sigchld_fd); if (sigismember(&mask, SIGTERM)) { if (!IsRebootCapable()) { Result<int> cs_result = CreateAndRegisterSignalFd(epoll, SIGTERM); if (!cs_result.ok()) { PLOG(FATAL) << cs_result.error(); Loading init/init.h +0 −2 Original line number Diff line number Diff line Loading @@ -28,8 +28,6 @@ namespace android { namespace init { extern int sigchld_fd; Parser CreateParser(ActionManager& action_manager, ServiceList& service_list); Parser CreateApexConfigParser(ActionManager& action_manager, ServiceList& service_list); Loading init/reboot.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -563,7 +563,7 @@ static void StopServices(const std::set<std::string>& services, std::chrono::mil } } if (timeout > 0ms) { WaitToBeReaped(sigchld_fd, pids, timeout); WaitToBeReaped(Service::GetSigchldFd(), pids, timeout); } else { // Even if we don't to wait for services to stop, we still optimistically reap zombies. ReapAnyOutstandingChildren(); Loading init/service.cpp +31 −1 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ #include <cutils/sockets.h> #include <processgroup/processgroup.h> #include <selinux/selinux.h> #include <sys/signalfd.h> #include <string> Loading Loading @@ -68,6 +69,7 @@ using android::base::make_scope_guard; using android::base::SetProperty; using android::base::StartsWith; using android::base::StringPrintf; using android::base::unique_fd; using android::base::WriteStringToFile; namespace android { Loading Loading @@ -136,7 +138,6 @@ static bool ExpandArgsAndExecv(const std::vector<std::string>& args, bool sigsto 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) Loading Loading @@ -792,6 +793,35 @@ void Service::SetMountNamespace() { mount_namespace_ = IsDefaultMountNamespaceReady() ? NS_DEFAULT : NS_BOOTSTRAP; } static int ThreadCount() { std::unique_ptr<DIR, decltype(&closedir)> dir(opendir("/proc/self/task"), closedir); if (!dir) { return -1; } int count = 0; dirent* entry; while ((entry = readdir(dir.get())) != nullptr) { if (entry->d_name[0] != '.') { count++; } } return count; } // Must be called BEFORE any threads are created. See also the sigprocmask() man page. unique_fd Service::CreateSigchldFd() { CHECK_EQ(ThreadCount(), 1); sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGCHLD); if (sigprocmask(SIG_BLOCK, &mask, nullptr) < 0) { PLOG(FATAL) << "Failed to block SIGCHLD"; } return unique_fd(signalfd(-1, &mask, SFD_CLOEXEC)); } void Service::SetStartedInFirstStage(pid_t pid) { LOG(INFO) << "adding first-stage service '" << name_ << "'..."; Loading init/service.h +5 −2 Original line number Diff line number Diff line Loading @@ -156,7 +156,10 @@ class Service { 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; } static int GetSigchldFd() { static int sigchld_fd = CreateSigchldFd().release(); return sigchld_fd; } private: void NotifyStateChange(const std::string& new_state) const; Loading @@ -169,10 +172,10 @@ class Service { void RunService(const std::vector<Descriptor>& descriptors, InterprocessFifo cgroups_activated, InterprocessFifo setsid_finished); void SetMountNamespace(); static ::android::base::unique_fd CreateSigchldFd(); 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_; Loading Loading
init/init.cpp +14 −27 Original line number Diff line number Diff line Loading @@ -117,7 +117,6 @@ namespace init { static int property_triggers_enabled = 0; int sigchld_fd = -1; static int sigterm_fd = -1; static int property_fd = -1; Loading Loading @@ -717,7 +716,7 @@ static void HandleSigtermSignal(const signalfd_siginfo& siginfo) { static void HandleSignalFd(int signal) { signalfd_siginfo siginfo; const int signal_fd = signal == SIGCHLD ? sigchld_fd : sigterm_fd; const int signal_fd = signal == SIGCHLD ? Service::GetSigchldFd() : 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"; Loading Loading @@ -751,20 +750,24 @@ static void UnblockSignals() { } } static Result<void> RegisterSignalFd(Epoll* epoll, int signal, int fd) { return epoll->RegisterHandler( fd, [signal]() { HandleSignalFd(signal); }, EPOLLIN | EPOLLPRI); } 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; if (sigprocmask(SIG_BLOCK, &mask, nullptr) == -1) { return ErrnoError() << "failed to block signal " << signal; } auto result = epoll->RegisterHandler( signal_fd.get(), [signal]() { HandleSignalFd(signal); }, EPOLLIN | EPOLLPRI); if (!result.ok()) { return result.error(); unique_fd signal_fd(signalfd(-1, &mask, SFD_CLOEXEC)); if (signal_fd.get() < 0) { return ErrnoError() << "failed to create signalfd for signal " << signal; } OR_RETURN(RegisterSignalFd(epoll, signal, signal_fd.get())); return signal_fd.release(); } Loading @@ -775,34 +778,18 @@ static void InstallSignalFdHandler(Epoll* epoll) { const struct sigaction act { .sa_flags = SA_NOCLDSTOP, .sa_handler = SIG_DFL }; 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 signals"; } // 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); } Result<int> cs_result = CreateAndRegisterSignalFd(epoll, SIGCHLD); Result<void> cs_result = RegisterSignalFd(epoll, SIGCHLD, Service::GetSigchldFd()); if (!cs_result.ok()) { PLOG(FATAL) << cs_result.error(); } sigchld_fd = cs_result.value(); Service::SetSigchldFd(sigchld_fd); if (sigismember(&mask, SIGTERM)) { if (!IsRebootCapable()) { Result<int> cs_result = CreateAndRegisterSignalFd(epoll, SIGTERM); if (!cs_result.ok()) { PLOG(FATAL) << cs_result.error(); Loading
init/init.h +0 −2 Original line number Diff line number Diff line Loading @@ -28,8 +28,6 @@ namespace android { namespace init { extern int sigchld_fd; Parser CreateParser(ActionManager& action_manager, ServiceList& service_list); Parser CreateApexConfigParser(ActionManager& action_manager, ServiceList& service_list); Loading
init/reboot.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -563,7 +563,7 @@ static void StopServices(const std::set<std::string>& services, std::chrono::mil } } if (timeout > 0ms) { WaitToBeReaped(sigchld_fd, pids, timeout); WaitToBeReaped(Service::GetSigchldFd(), pids, timeout); } else { // Even if we don't to wait for services to stop, we still optimistically reap zombies. ReapAnyOutstandingChildren(); Loading
init/service.cpp +31 −1 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ #include <cutils/sockets.h> #include <processgroup/processgroup.h> #include <selinux/selinux.h> #include <sys/signalfd.h> #include <string> Loading Loading @@ -68,6 +69,7 @@ using android::base::make_scope_guard; using android::base::SetProperty; using android::base::StartsWith; using android::base::StringPrintf; using android::base::unique_fd; using android::base::WriteStringToFile; namespace android { Loading Loading @@ -136,7 +138,6 @@ static bool ExpandArgsAndExecv(const std::vector<std::string>& args, bool sigsto 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) Loading Loading @@ -792,6 +793,35 @@ void Service::SetMountNamespace() { mount_namespace_ = IsDefaultMountNamespaceReady() ? NS_DEFAULT : NS_BOOTSTRAP; } static int ThreadCount() { std::unique_ptr<DIR, decltype(&closedir)> dir(opendir("/proc/self/task"), closedir); if (!dir) { return -1; } int count = 0; dirent* entry; while ((entry = readdir(dir.get())) != nullptr) { if (entry->d_name[0] != '.') { count++; } } return count; } // Must be called BEFORE any threads are created. See also the sigprocmask() man page. unique_fd Service::CreateSigchldFd() { CHECK_EQ(ThreadCount(), 1); sigset_t mask; sigemptyset(&mask); sigaddset(&mask, SIGCHLD); if (sigprocmask(SIG_BLOCK, &mask, nullptr) < 0) { PLOG(FATAL) << "Failed to block SIGCHLD"; } return unique_fd(signalfd(-1, &mask, SFD_CLOEXEC)); } void Service::SetStartedInFirstStage(pid_t pid) { LOG(INFO) << "adding first-stage service '" << name_ << "'..."; Loading
init/service.h +5 −2 Original line number Diff line number Diff line Loading @@ -156,7 +156,10 @@ class Service { 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; } static int GetSigchldFd() { static int sigchld_fd = CreateSigchldFd().release(); return sigchld_fd; } private: void NotifyStateChange(const std::string& new_state) const; Loading @@ -169,10 +172,10 @@ class Service { void RunService(const std::vector<Descriptor>& descriptors, InterprocessFifo cgroups_activated, InterprocessFifo setsid_finished); void SetMountNamespace(); static ::android::base::unique_fd CreateSigchldFd(); 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_; Loading