Loading init/epoll.cpp +15 −4 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ #include <functional> #include <map> #include <android-base/logging.h> namespace android { namespace init { Loading @@ -42,8 +44,11 @@ Result<void> Epoll::RegisterHandler(int fd, Handler handler, uint32_t events) { if (!events) { return Error() << "Must specify events"; } auto sp = std::make_shared<decltype(handler)>(std::move(handler)); auto [it, inserted] = epoll_handlers_.emplace(fd, std::move(sp)); Info info; info.events = events; info.handler = std::make_shared<decltype(handler)>(std::move(handler)); auto [it, inserted] = epoll_handlers_.emplace(fd, std::move(info)); if (!inserted) { return Error() << "Cannot specify two epoll handlers for a given FD"; } Loading Loading @@ -84,8 +89,14 @@ Result<std::vector<std::shared_ptr<Epoll::Handler>>> Epoll::Wait( } std::vector<std::shared_ptr<Handler>> pending_functions; for (int i = 0; i < num_events; ++i) { auto sp = *reinterpret_cast<std::shared_ptr<Handler>*>(ev[i].data.ptr); pending_functions.emplace_back(std::move(sp)); auto& info = *reinterpret_cast<Info*>(ev[i].data.ptr); if ((info.events & (EPOLLIN | EPOLLPRI)) == (EPOLLIN | EPOLLPRI) && (ev[i].events & EPOLLIN) != ev[i].events) { // This handler wants to know about exception events, and just got one. // Log something informational. LOG(ERROR) << "Received unexpected epoll event set: " << ev[i].events; } pending_functions.emplace_back(info.handler); } return pending_functions; Loading init/epoll.h +6 −1 Original line number Diff line number Diff line Loading @@ -46,8 +46,13 @@ class Epoll { std::optional<std::chrono::milliseconds> timeout); private: struct Info { std::shared_ptr<Handler> handler; uint32_t events; }; android::base::unique_fd epoll_fd_; std::map<int, std::shared_ptr<Handler>> epoll_handlers_; std::map<int, Info> epoll_handlers_; }; } // namespace init Loading init/init.cpp +47 −4 Original line number Diff line number Diff line Loading @@ -33,7 +33,10 @@ #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ #include <sys/_system_properties.h> #include <filesystem> #include <fstream> #include <functional> #include <iostream> #include <map> #include <memory> #include <mutex> Loading Loading @@ -695,10 +698,10 @@ static void HandleSigtermSignal(const signalfd_siginfo& siginfo) { static constexpr std::chrono::milliseconds kDiagnosticTimeout = 10s; static void HandleSignalFd() { static void HandleSignalFd(bool one_off) { signalfd_siginfo siginfo; auto started = std::chrono::steady_clock::now(); for (;;) { do { ssize_t bytes_read = TEMP_FAILURE_RETRY(read(signal_fd, &siginfo, sizeof(siginfo))); if (bytes_read < 0 && errno == EAGAIN) { auto now = std::chrono::steady_clock::now(); Loading @@ -716,7 +719,7 @@ static void HandleSignalFd() { return; } break; } } while (!one_off); switch (siginfo.ssi_signo) { case SIGCHLD: Loading Loading @@ -776,7 +779,9 @@ static void InstallSignalFdHandler(Epoll* epoll) { PLOG(FATAL) << "failed to create signalfd"; } if (auto result = epoll->RegisterHandler(signal_fd, HandleSignalFd); !result.ok()) { constexpr int flags = EPOLLIN | EPOLLPRI; auto handler = std::bind(HandleSignalFd, false); if (auto result = epoll->RegisterHandler(signal_fd, handler, flags); !result.ok()) { LOG(FATAL) << result.error(); } } Loading Loading @@ -905,6 +910,32 @@ static Result<void> ConnectEarlyStageSnapuserdAction(const BuiltinArguments& arg return {}; } static void DumpPidFds(const std::string& prefix, pid_t pid) { std::error_code ec; std::string proc_dir = "/proc/" + std::to_string(pid) + "/fd"; for (const auto& entry : std::filesystem::directory_iterator(proc_dir)) { std::string target; if (android::base::Readlink(entry.path(), &target)) { LOG(ERROR) << prefix << target; } else { LOG(ERROR) << prefix << entry.path(); } } } static void DumpFile(const std::string& prefix, const std::string& file) { std::ifstream fp(file); if (!fp) { LOG(ERROR) << "Could not open " << file; return; } std::string line; while (std::getline(fp, line)) { LOG(ERROR) << prefix << line; } } int SecondStageMain(int argc, char** argv) { if (REBOOT_BOOTLOADER_ON_PANIC) { InstallRebootSignalHandlers(); Loading Loading @@ -1114,11 +1145,23 @@ int SecondStageMain(int argc, char** argv) { (*function)(); } } else if (Service::is_exec_service_running()) { static bool dumped_diagnostics = false; std::chrono::duration<double> waited = std::chrono::steady_clock::now() - Service::exec_service_started(); if (waited >= kDiagnosticTimeout) { LOG(ERROR) << "Exec service is hung? Waited " << waited.count() << " without SIGCHLD"; if (!dumped_diagnostics) { DumpPidFds("exec service opened: ", Service::exec_service_pid()); std::string status_file = "/proc/" + std::to_string(Service::exec_service_pid()) + "/status"; DumpFile("exec service: ", status_file); dumped_diagnostics = true; LOG(INFO) << "Attempting to handle any stuck SIGCHLDs..."; HandleSignalFd(true); } } } if (!IsShuttingDown()) { Loading init/service.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -127,6 +127,7 @@ 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; pid_t Service::exec_service_pid_ = -1; std::chrono::time_point<std::chrono::steady_clock> Service::exec_service_started_; Service::Service(const std::string& name, Subcontext* subcontext_for_restart_commands, Loading Loading @@ -395,6 +396,7 @@ Result<void> Service::ExecStart() { flags_ |= SVC_EXEC; is_exec_service_running_ = true; exec_service_pid_ = pid_; exec_service_started_ = std::chrono::steady_clock::now(); LOG(INFO) << "SVC_EXEC service '" << name_ << "' pid " << pid_ << " (uid " << proc_attr_.uid Loading init/service.h +1 −0 Original line number Diff line number Diff line Loading @@ -103,6 +103,7 @@ class Service { size_t CheckAllCommands() const { return onrestart_.CheckAllCommands(); } static bool is_exec_service_running() { return is_exec_service_running_; } static pid_t exec_service_pid() { return exec_service_pid_; } static std::chrono::time_point<std::chrono::steady_clock> exec_service_started() { return exec_service_started_; } Loading Loading
init/epoll.cpp +15 −4 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ #include <functional> #include <map> #include <android-base/logging.h> namespace android { namespace init { Loading @@ -42,8 +44,11 @@ Result<void> Epoll::RegisterHandler(int fd, Handler handler, uint32_t events) { if (!events) { return Error() << "Must specify events"; } auto sp = std::make_shared<decltype(handler)>(std::move(handler)); auto [it, inserted] = epoll_handlers_.emplace(fd, std::move(sp)); Info info; info.events = events; info.handler = std::make_shared<decltype(handler)>(std::move(handler)); auto [it, inserted] = epoll_handlers_.emplace(fd, std::move(info)); if (!inserted) { return Error() << "Cannot specify two epoll handlers for a given FD"; } Loading Loading @@ -84,8 +89,14 @@ Result<std::vector<std::shared_ptr<Epoll::Handler>>> Epoll::Wait( } std::vector<std::shared_ptr<Handler>> pending_functions; for (int i = 0; i < num_events; ++i) { auto sp = *reinterpret_cast<std::shared_ptr<Handler>*>(ev[i].data.ptr); pending_functions.emplace_back(std::move(sp)); auto& info = *reinterpret_cast<Info*>(ev[i].data.ptr); if ((info.events & (EPOLLIN | EPOLLPRI)) == (EPOLLIN | EPOLLPRI) && (ev[i].events & EPOLLIN) != ev[i].events) { // This handler wants to know about exception events, and just got one. // Log something informational. LOG(ERROR) << "Received unexpected epoll event set: " << ev[i].events; } pending_functions.emplace_back(info.handler); } return pending_functions; Loading
init/epoll.h +6 −1 Original line number Diff line number Diff line Loading @@ -46,8 +46,13 @@ class Epoll { std::optional<std::chrono::milliseconds> timeout); private: struct Info { std::shared_ptr<Handler> handler; uint32_t events; }; android::base::unique_fd epoll_fd_; std::map<int, std::shared_ptr<Handler>> epoll_handlers_; std::map<int, Info> epoll_handlers_; }; } // namespace init Loading
init/init.cpp +47 −4 Original line number Diff line number Diff line Loading @@ -33,7 +33,10 @@ #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ #include <sys/_system_properties.h> #include <filesystem> #include <fstream> #include <functional> #include <iostream> #include <map> #include <memory> #include <mutex> Loading Loading @@ -695,10 +698,10 @@ static void HandleSigtermSignal(const signalfd_siginfo& siginfo) { static constexpr std::chrono::milliseconds kDiagnosticTimeout = 10s; static void HandleSignalFd() { static void HandleSignalFd(bool one_off) { signalfd_siginfo siginfo; auto started = std::chrono::steady_clock::now(); for (;;) { do { ssize_t bytes_read = TEMP_FAILURE_RETRY(read(signal_fd, &siginfo, sizeof(siginfo))); if (bytes_read < 0 && errno == EAGAIN) { auto now = std::chrono::steady_clock::now(); Loading @@ -716,7 +719,7 @@ static void HandleSignalFd() { return; } break; } } while (!one_off); switch (siginfo.ssi_signo) { case SIGCHLD: Loading Loading @@ -776,7 +779,9 @@ static void InstallSignalFdHandler(Epoll* epoll) { PLOG(FATAL) << "failed to create signalfd"; } if (auto result = epoll->RegisterHandler(signal_fd, HandleSignalFd); !result.ok()) { constexpr int flags = EPOLLIN | EPOLLPRI; auto handler = std::bind(HandleSignalFd, false); if (auto result = epoll->RegisterHandler(signal_fd, handler, flags); !result.ok()) { LOG(FATAL) << result.error(); } } Loading Loading @@ -905,6 +910,32 @@ static Result<void> ConnectEarlyStageSnapuserdAction(const BuiltinArguments& arg return {}; } static void DumpPidFds(const std::string& prefix, pid_t pid) { std::error_code ec; std::string proc_dir = "/proc/" + std::to_string(pid) + "/fd"; for (const auto& entry : std::filesystem::directory_iterator(proc_dir)) { std::string target; if (android::base::Readlink(entry.path(), &target)) { LOG(ERROR) << prefix << target; } else { LOG(ERROR) << prefix << entry.path(); } } } static void DumpFile(const std::string& prefix, const std::string& file) { std::ifstream fp(file); if (!fp) { LOG(ERROR) << "Could not open " << file; return; } std::string line; while (std::getline(fp, line)) { LOG(ERROR) << prefix << line; } } int SecondStageMain(int argc, char** argv) { if (REBOOT_BOOTLOADER_ON_PANIC) { InstallRebootSignalHandlers(); Loading Loading @@ -1114,11 +1145,23 @@ int SecondStageMain(int argc, char** argv) { (*function)(); } } else if (Service::is_exec_service_running()) { static bool dumped_diagnostics = false; std::chrono::duration<double> waited = std::chrono::steady_clock::now() - Service::exec_service_started(); if (waited >= kDiagnosticTimeout) { LOG(ERROR) << "Exec service is hung? Waited " << waited.count() << " without SIGCHLD"; if (!dumped_diagnostics) { DumpPidFds("exec service opened: ", Service::exec_service_pid()); std::string status_file = "/proc/" + std::to_string(Service::exec_service_pid()) + "/status"; DumpFile("exec service: ", status_file); dumped_diagnostics = true; LOG(INFO) << "Attempting to handle any stuck SIGCHLDs..."; HandleSignalFd(true); } } } if (!IsShuttingDown()) { Loading
init/service.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -127,6 +127,7 @@ 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; pid_t Service::exec_service_pid_ = -1; std::chrono::time_point<std::chrono::steady_clock> Service::exec_service_started_; Service::Service(const std::string& name, Subcontext* subcontext_for_restart_commands, Loading Loading @@ -395,6 +396,7 @@ Result<void> Service::ExecStart() { flags_ |= SVC_EXEC; is_exec_service_running_ = true; exec_service_pid_ = pid_; exec_service_started_ = std::chrono::steady_clock::now(); LOG(INFO) << "SVC_EXEC service '" << name_ << "' pid " << pid_ << " (uid " << proc_attr_.uid Loading
init/service.h +1 −0 Original line number Diff line number Diff line Loading @@ -103,6 +103,7 @@ class Service { size_t CheckAllCommands() const { return onrestart_.CheckAllCommands(); } static bool is_exec_service_running() { return is_exec_service_running_; } static pid_t exec_service_pid() { return exec_service_pid_; } static std::chrono::time_point<std::chrono::steady_clock> exec_service_started() { return exec_service_started_; } Loading