1471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo// Copyright 2015 The Chromium OS Authors. All rights reserved. 2471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo// Use of this source code is governed by a BSD-style license that can be 3471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo// found in the LICENSE file. 4471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo 59ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include "brillo/process_reaper.h" 6471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo 7471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo#include <sys/signalfd.h> 8471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo#include <sys/types.h> 9471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo#include <sys/wait.h> 10471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo 11471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo#include <base/bind.h> 12471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo#include <base/posix/eintr_wrapper.h> 139ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/asynchronous_signal_handler.h> 149ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/daemons/daemon.h> 159ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko#include <brillo/location_logging.h> 16471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo 179ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenkonamespace brillo { 18471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo 19471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex DeymoProcessReaper::~ProcessReaper() { 2038c16335b69d8f6611746e6267bc68105e237e97Alex Deymo Unregister(); 21471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo} 22471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo 2338c16335b69d8f6611746e6267bc68105e237e97Alex Deymovoid ProcessReaper::Register( 249ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko AsynchronousSignalHandlerInterface* async_signal_handler) { 2538c16335b69d8f6611746e6267bc68105e237e97Alex Deymo CHECK(!async_signal_handler_); 26471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo async_signal_handler_ = async_signal_handler; 27471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo async_signal_handler->RegisterHandler( 28471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo SIGCHLD, 29471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo base::Bind(&ProcessReaper::HandleSIGCHLD, base::Unretained(this))); 30471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo} 31471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo 32471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymovoid ProcessReaper::Unregister() { 3338c16335b69d8f6611746e6267bc68105e237e97Alex Deymo if (!async_signal_handler_) 3438c16335b69d8f6611746e6267bc68105e237e97Alex Deymo return; 3538c16335b69d8f6611746e6267bc68105e237e97Alex Deymo async_signal_handler_->UnregisterHandler(SIGCHLD); 3638c16335b69d8f6611746e6267bc68105e237e97Alex Deymo async_signal_handler_ = nullptr; 37471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo} 38471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo 39471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymobool ProcessReaper::WatchForChild(const tracked_objects::Location& from_here, 40471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo pid_t pid, 41471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo const ChildCallback& callback) { 42471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo if (watched_processes_.find(pid) != watched_processes_.end()) 43471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo return false; 44471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo watched_processes_.emplace(pid, WatchedProcess{from_here, callback}); 45471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo return true; 46471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo} 47471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo 48b6a5c6113b0b7ae947c5a1729d4b9d08287a83e2Paul Stewartbool ProcessReaper::ForgetChild(pid_t pid) { 49b6a5c6113b0b7ae947c5a1729d4b9d08287a83e2Paul Stewart return watched_processes_.erase(pid) != 0; 50b6a5c6113b0b7ae947c5a1729d4b9d08287a83e2Paul Stewart} 51b6a5c6113b0b7ae947c5a1729d4b9d08287a83e2Paul Stewart 522fd46ba1458275cd16b0949675bff70cc8abcdadChristopher Wileybool ProcessReaper::HandleSIGCHLD( 532fd46ba1458275cd16b0949675bff70cc8abcdadChristopher Wiley const struct signalfd_siginfo& /* sigfd_info */) { 54471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo // One SIGCHLD may correspond to multiple terminated children, so ignore 55471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo // sigfd_info and reap any available children. 56471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo while (true) { 57471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo siginfo_t info; 58471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo info.si_pid = 0; 59471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo int rc = HANDLE_EINTR(waitid(P_ALL, 0, &info, WNOHANG | WEXITED)); 60471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo 61471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo if (rc == -1) { 62471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo if (errno != ECHILD) { 63471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo PLOG(ERROR) << "waitid failed"; 64471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo } 65471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo break; 66471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo } 67471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo 68471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo if (info.si_pid == 0) { 69471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo break; 70471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo } 71471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo 72471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo auto proc = watched_processes_.find(info.si_pid); 73471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo if (proc == watched_processes_.end()) { 744a71a24c29810f08dfa39610e2c6f22e134e3df1Jorge Lucangeli Obes LOG(INFO) << "Untracked process " << info.si_pid 75471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo << " terminated with status " << info.si_status 76471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo << " (code = " << info.si_code << ")"; 77471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo } else { 78471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo DVLOG_LOC(proc->second.location, 1) 79471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo << "Process " << info.si_pid << " terminated with status " 80471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo << info.si_status << " (code = " << info.si_code << ")"; 81471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo ChildCallback callback = std::move(proc->second.callback); 82471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo watched_processes_.erase(proc); 83471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo callback.Run(info); 84471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo } 85471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo } 86471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo 87471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo // Return false to indicate that our handler should not be uninstalled. 88471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo return false; 89471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo} 90471776dcf9a6a861e3f9f63121fd13b1a1b3f180Alex Deymo 919ed0cab99f18acb3570a35e9408f24355f6b8324Alex Vakulenko} // namespace brillo 92