auto pid = siginfo.si_pid; if (pid == 0) returnfalse;
// 这时我们知道我们有一个僵尸进程, 所以在此之前无论何时返回我们都使用 scopeguard 来回收这个进程 // 我们不想要过早的回收僵尸进程 as in Service::Reap(), we kill(-pid, ...) // 并且我们希望进程在整个使用过程中(以及将来的使用过程中)仍然保持有效 auto reaper = make_scope_guard([pid] { TEMP_FAILURE_RETRY(waitpid(pid, nullptr, WNOHANG)); });
std::string name; std::string wait_string; Service* service = nullptr;
if (PropertyChildReap(pid)) { name = "Async property child"; } elseif (SubcontextChildReap(pid)) { name = "Subcontext"; } else { service = ServiceList::GetInstance().FindService(pid, &Service::pid); // ------------------------------------- (1)
if (service) { name = StringPrintf("Service '%s' (pid %d)", service->name().c_str(), pid); if (service->flags() & SVC_EXEC) { auto exec_duration = boot_clock::now() - service->time_started(); auto exec_duration_ms = std::chrono::duration_cast<std::chrono::milliseconds>(exec_duration).count(); wait_string = StringPrintf(" waiting took %f seconds", exec_duration_ms / 1000.0f); } } else { name = StringPrintf("Untracked pid %d", pid); } }
if (siginfo.si_code == CLD_EXITED) { LOG(INFO) << name << " exited with status " << siginfo.si_status << wait_string; } else { LOG(INFO) << name << " received signal " << siginfo.si_status << wait_string; }
// Remove any descriptor resources we may have created. std::for_each(descriptors_.begin(), descriptors_.end(), std::bind(&DescriptorInfo::Clean, std::placeholders::_1));
for (constauto& f : reap_callbacks_) { f(siginfo); }
if (flags_ & SVC_EXEC) UnSetExec(); // -------------------------------- (2)
// Oneshot processes go into the disabled state on exit, // except when manually restarted. if ((flags_ & SVC_ONESHOT) && !(flags_ & SVC_RESTART)) { flags_ |= SVC_DISABLED; }
// Disabled and reset processes do not get restarted automatically. if (flags_ & (SVC_DISABLED | SVC_RESET)) { NotifyStateChange("stopped"); return; }
// If we crash > 4 times in 4 minutes, reboot into recovery. boot_clock::time_point now = boot_clock::now(); if ((flags_ & SVC_CRITICAL) && !(flags_ & SVC_RESTART)) { if (now < time_crashed_ + 4min) { if (++crash_count_ > 4) { LOG(FATAL) << "critical process '" << name_ << "' exited 4 times in 4 minutes"; } } else { time_crashed_ = now; crash_count_ = 1; } }
/* Get the basic filesystem setup we need put together in the initramdisk * on / and then we'll let the rc file figure out the rest. -- 创建文件系统 */ mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"); mkdir("/dev/pts", 0755); mkdir("/dev/socket", 0755); mount("devpts", "/dev/pts", "devpts", 0, NULL); #define MAKE_STR(x) __STRING(x) mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC));
// We're in the kernel domain, so re-exec init to transition to the init domain now // that the SELinux policy has been loaded. if (selinux_android_restorecon("/init", 0) == -1) { PLOG(FATAL) << "restorecon failed of /init failed"; }
// execv() only returns if an error happened, in which case we // panic and never fall through this conditional. PLOG(FATAL) << "execv(\"" << path << "\") failed"; }
// Repeat mix_hwrng_into_linux_rng in case /dev/hw_random or /dev/random // wasn't ready immediately after wait_for_coldboot_done am.QueueBuiltinAction(MixHwrngIntoLinuxRngAction, "MixHwrngIntoLinuxRng");