接上文
1. 监控service异常退出
对于init启动的service,如果没有指定oneshort(一次性)的option,则默认为常驻service。在此情况下,当servcie意外退出,init将监控到并重启service
首先,在InstallSignalFdHandler中注册SIGCHLD信号的处理函数,用于监听init子进程的终止。SIGCHLD会监听到子进程的终止、暂停、恢复三个状态。init在注册SIGCHLD时,设置了SA_NOCLDSTOP这个flag,其作用是不监听暂停、恢复状态,只关注终止状态。
core/init/init.cpp
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).
const struct sigaction act { .sa_flags = SA_NOCLDSTOP, .sa_handler = SIG_DFL };
sigaction(SIGCHLD, &act, nullptr);
// 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<void> cs_result = RegisterSignalFd(epoll, SIGCHLD, Service::GetSigchldFd());
if (!cs_result.ok()) {
PLOG(FATAL) << cs_result.error();
}
if (!IsRebootCapable()) {
Result<int> cs_result = CreateAndRegisterSignalFd(epoll, SIGTERM);
if (!cs_result.ok()) {
PLOG(FATAL) << cs_result.error();
}
sigterm_fd = cs_result.value();
}
}
而具体SIGCHLD的监听处理,是由epoll来实现的。在RegisterSignalFd中:
static Result<void> RegisterSignalFd(Epoll* epoll, int signal, int fd) {
return epoll->RegisterHandler(
fd, [signal]() {
HandleSignalFd(signal); }, EPOLLIN | EPOLLPRI);
}
指明了信号处理函数HandleSignalFd:
static void HandleSignalFd(int signal) {
...
switch (siginfo.ssi_signo) {
case SIGCHLD:
ReapAnyOutstandingChildren();
break;
case SIGTERM:
HandleSigtermSignal(siginfo);
break;
default:
LOG(ERROR) << "signal_fd: received unexpected signal " << siginfo.ssi_signo;
break;
}
}
收到SIGCHLD信号时,会调用ReapAnyOutstandingChildren
core/init/sigchld_handler.cpp
std::set<pid_t> ReapAnyOutstandingChildren() {
std::set<pid_t> reaped_pids;
for (;;) {
const pid_t pid = ReapOneProcess();
if (pid <= 0) {
return reaped_pids;
}
reaped_pids.emplace(