xref: /aosp_15_r20/external/libbrillo/brillo/process.cc (revision 1a96fba65179ea7d3f56207137718607415c5953)
1*1a96fba6SXin Li // Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2*1a96fba6SXin Li // Use of this source code is governed by a BSD-style license that can be
3*1a96fba6SXin Li // found in the LICENSE file.
4*1a96fba6SXin Li 
5*1a96fba6SXin Li #include "brillo/process.h"
6*1a96fba6SXin Li 
7*1a96fba6SXin Li #ifdef __BIONIC__
8*1a96fba6SXin Li #include <android/fdsan.h>
9*1a96fba6SXin Li #endif
10*1a96fba6SXin Li 
11*1a96fba6SXin Li #include <fcntl.h>
12*1a96fba6SXin Li #include <signal.h>
13*1a96fba6SXin Li #include <stdint.h>
14*1a96fba6SXin Li #include <sys/mman.h>
15*1a96fba6SXin Li #include <sys/stat.h>
16*1a96fba6SXin Li #include <sys/types.h>
17*1a96fba6SXin Li #include <sys/wait.h>
18*1a96fba6SXin Li #include <unistd.h>
19*1a96fba6SXin Li 
20*1a96fba6SXin Li #include <map>
21*1a96fba6SXin Li #include <memory>
22*1a96fba6SXin Li 
23*1a96fba6SXin Li #include <base/files/file_path.h>
24*1a96fba6SXin Li #include <base/files/file_util.h>
25*1a96fba6SXin Li #include <base/logging.h>
26*1a96fba6SXin Li #include <base/posix/eintr_wrapper.h>
27*1a96fba6SXin Li #include <base/posix/file_descriptor_shuffle.h>
28*1a96fba6SXin Li #include <base/process/process_metrics.h>
29*1a96fba6SXin Li #include <base/strings/string_number_conversions.h>
30*1a96fba6SXin Li #include <base/strings/string_util.h>
31*1a96fba6SXin Li #include <base/time/time.h>
32*1a96fba6SXin Li 
33*1a96fba6SXin Li #ifndef __linux__
34*1a96fba6SXin Li #define setresuid(_u1, _u2, _u3) setreuid(_u1, _u2)
35*1a96fba6SXin Li #define setresgid(_g1, _g2, _g3) setregid(_g1, _g2)
36*1a96fba6SXin Li #endif  // !__linux__
37*1a96fba6SXin Li 
38*1a96fba6SXin Li namespace brillo {
39*1a96fba6SXin Li 
ReturnTrue()40*1a96fba6SXin Li bool ReturnTrue() {
41*1a96fba6SXin Li   return true;
42*1a96fba6SXin Li }
43*1a96fba6SXin Li 
Process()44*1a96fba6SXin Li Process::Process() {}
45*1a96fba6SXin Li 
~Process()46*1a96fba6SXin Li Process::~Process() {}
47*1a96fba6SXin Li 
ProcessExists(pid_t pid)48*1a96fba6SXin Li bool Process::ProcessExists(pid_t pid) {
49*1a96fba6SXin Li   return base::DirectoryExists(
50*1a96fba6SXin Li       base::FilePath(base::StringPrintf("/proc/%d", pid)));
51*1a96fba6SXin Li }
52*1a96fba6SXin Li 
ProcessImpl()53*1a96fba6SXin Li ProcessImpl::ProcessImpl()
54*1a96fba6SXin Li     : pid_(0),
55*1a96fba6SXin Li       uid_(-1),
56*1a96fba6SXin Li       gid_(-1),
57*1a96fba6SXin Li       pre_exec_(base::Bind(&ReturnTrue)),
58*1a96fba6SXin Li       search_path_(false),
59*1a96fba6SXin Li       inherit_parent_signal_mask_(false),
60*1a96fba6SXin Li       close_unused_file_descriptors_(false) {}
61*1a96fba6SXin Li 
~ProcessImpl()62*1a96fba6SXin Li ProcessImpl::~ProcessImpl() {
63*1a96fba6SXin Li   Reset(0);
64*1a96fba6SXin Li }
65*1a96fba6SXin Li 
AddArg(const std::string & arg)66*1a96fba6SXin Li void ProcessImpl::AddArg(const std::string& arg) {
67*1a96fba6SXin Li   arguments_.push_back(arg);
68*1a96fba6SXin Li }
69*1a96fba6SXin Li 
RedirectInput(const std::string & input_file)70*1a96fba6SXin Li void ProcessImpl::RedirectInput(const std::string& input_file) {
71*1a96fba6SXin Li   input_file_ = input_file;
72*1a96fba6SXin Li }
73*1a96fba6SXin Li 
RedirectOutput(const std::string & output_file)74*1a96fba6SXin Li void ProcessImpl::RedirectOutput(const std::string& output_file) {
75*1a96fba6SXin Li   output_file_ = output_file;
76*1a96fba6SXin Li }
77*1a96fba6SXin Li 
RedirectUsingPipe(int child_fd,bool is_input)78*1a96fba6SXin Li void ProcessImpl::RedirectUsingPipe(int child_fd, bool is_input) {
79*1a96fba6SXin Li   PipeInfo info;
80*1a96fba6SXin Li   info.is_input_ = is_input;
81*1a96fba6SXin Li   info.is_bound_ = false;
82*1a96fba6SXin Li   pipe_map_[child_fd] = info;
83*1a96fba6SXin Li }
84*1a96fba6SXin Li 
BindFd(int parent_fd,int child_fd)85*1a96fba6SXin Li void ProcessImpl::BindFd(int parent_fd, int child_fd) {
86*1a96fba6SXin Li   PipeInfo info;
87*1a96fba6SXin Li   info.is_bound_ = true;
88*1a96fba6SXin Li 
89*1a96fba6SXin Li   // info.child_fd_ is the 'child half' of the pipe, which gets dup2()ed into
90*1a96fba6SXin Li   // place over child_fd. Since we already have the child we want to dup2() into
91*1a96fba6SXin Li   // place, we can set info.child_fd_ to parent_fd and leave info.parent_fd_
92*1a96fba6SXin Li   // invalid.
93*1a96fba6SXin Li   info.child_fd_ = parent_fd;
94*1a96fba6SXin Li   info.parent_fd_ = -1;
95*1a96fba6SXin Li   pipe_map_[child_fd] = info;
96*1a96fba6SXin Li }
97*1a96fba6SXin Li 
SetCloseUnusedFileDescriptors(bool close_unused_fds)98*1a96fba6SXin Li void ProcessImpl::SetCloseUnusedFileDescriptors(bool close_unused_fds) {
99*1a96fba6SXin Li   close_unused_file_descriptors_ = close_unused_fds;
100*1a96fba6SXin Li }
101*1a96fba6SXin Li 
SetUid(uid_t uid)102*1a96fba6SXin Li void ProcessImpl::SetUid(uid_t uid) {
103*1a96fba6SXin Li   uid_ = uid;
104*1a96fba6SXin Li }
105*1a96fba6SXin Li 
SetGid(gid_t gid)106*1a96fba6SXin Li void ProcessImpl::SetGid(gid_t gid) {
107*1a96fba6SXin Li   gid_ = gid;
108*1a96fba6SXin Li }
109*1a96fba6SXin Li 
SetCapabilities(uint64_t)110*1a96fba6SXin Li void ProcessImpl::SetCapabilities(uint64_t /*capmask*/) {
111*1a96fba6SXin Li   // No-op, since ProcessImpl does not support sandboxing.
112*1a96fba6SXin Li   return;
113*1a96fba6SXin Li }
114*1a96fba6SXin Li 
ApplySyscallFilter(const std::string &)115*1a96fba6SXin Li void ProcessImpl::ApplySyscallFilter(const std::string& /*path*/) {
116*1a96fba6SXin Li   // No-op, since ProcessImpl does not support sandboxing.
117*1a96fba6SXin Li   return;
118*1a96fba6SXin Li }
119*1a96fba6SXin Li 
EnterNewPidNamespace()120*1a96fba6SXin Li void ProcessImpl::EnterNewPidNamespace() {
121*1a96fba6SXin Li   enter_new_pid_namespace_ = true;
122*1a96fba6SXin Li   return;
123*1a96fba6SXin Li }
124*1a96fba6SXin Li 
SetInheritParentSignalMask(bool inherit)125*1a96fba6SXin Li void ProcessImpl::SetInheritParentSignalMask(bool inherit) {
126*1a96fba6SXin Li   inherit_parent_signal_mask_ = inherit;
127*1a96fba6SXin Li }
128*1a96fba6SXin Li 
SetPreExecCallback(const PreExecCallback & cb)129*1a96fba6SXin Li void ProcessImpl::SetPreExecCallback(const PreExecCallback& cb) {
130*1a96fba6SXin Li   pre_exec_ = cb;
131*1a96fba6SXin Li }
132*1a96fba6SXin Li 
SetSearchPath(bool search_path)133*1a96fba6SXin Li void ProcessImpl::SetSearchPath(bool search_path) {
134*1a96fba6SXin Li   search_path_ = search_path;
135*1a96fba6SXin Li }
136*1a96fba6SXin Li 
GetPipe(int child_fd)137*1a96fba6SXin Li int ProcessImpl::GetPipe(int child_fd) {
138*1a96fba6SXin Li   PipeMap::iterator i = pipe_map_.find(child_fd);
139*1a96fba6SXin Li   if (i == pipe_map_.end())
140*1a96fba6SXin Li     return -1;
141*1a96fba6SXin Li   else
142*1a96fba6SXin Li     return i->second.parent_fd_;
143*1a96fba6SXin Li }
144*1a96fba6SXin Li 
PopulatePipeMap()145*1a96fba6SXin Li bool ProcessImpl::PopulatePipeMap() {
146*1a96fba6SXin Li   for (PipeMap::iterator i = pipe_map_.begin(); i != pipe_map_.end(); ++i) {
147*1a96fba6SXin Li     if (i->second.is_bound_) {
148*1a96fba6SXin Li       // already have a parent fd, and the child fd gets dup()ed later.
149*1a96fba6SXin Li       continue;
150*1a96fba6SXin Li     }
151*1a96fba6SXin Li     int pipefds[2];
152*1a96fba6SXin Li     if (pipe(pipefds) < 0) {
153*1a96fba6SXin Li       int saved_errno = errno;
154*1a96fba6SXin Li       LOG(ERROR) << "pipe call failed with: " << saved_errno;
155*1a96fba6SXin Li       return false;
156*1a96fba6SXin Li     }
157*1a96fba6SXin Li     if (i->second.is_input_) {
158*1a96fba6SXin Li       // pipe is an input from the prospective of the child.
159*1a96fba6SXin Li       i->second.parent_fd_ = pipefds[1];
160*1a96fba6SXin Li       i->second.child_fd_ = pipefds[0];
161*1a96fba6SXin Li     } else {
162*1a96fba6SXin Li       i->second.parent_fd_ = pipefds[0];
163*1a96fba6SXin Li       i->second.child_fd_ = pipefds[1];
164*1a96fba6SXin Li     }
165*1a96fba6SXin Li   }
166*1a96fba6SXin Li   return true;
167*1a96fba6SXin Li }
168*1a96fba6SXin Li 
IsFileDescriptorInPipeMap(int fd) const169*1a96fba6SXin Li bool ProcessImpl::IsFileDescriptorInPipeMap(int fd) const {
170*1a96fba6SXin Li   for (const auto& pipe : pipe_map_) {
171*1a96fba6SXin Li     if (fd == pipe.second.parent_fd_ || fd == pipe.second.child_fd_ ||
172*1a96fba6SXin Li         fd == pipe.first) {
173*1a96fba6SXin Li       return true;
174*1a96fba6SXin Li     }
175*1a96fba6SXin Li   }
176*1a96fba6SXin Li   return false;
177*1a96fba6SXin Li }
178*1a96fba6SXin Li 
CloseUnusedFileDescriptors()179*1a96fba6SXin Li void ProcessImpl::CloseUnusedFileDescriptors() {
180*1a96fba6SXin Li   size_t max_fds = base::GetMaxFds();
181*1a96fba6SXin Li   for (size_t i = 0; i < max_fds; i++) {
182*1a96fba6SXin Li     const int fd = static_cast<int>(i);
183*1a96fba6SXin Li 
184*1a96fba6SXin Li     // Ignore STD file descriptors.
185*1a96fba6SXin Li     if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO) {
186*1a96fba6SXin Li       continue;
187*1a96fba6SXin Li     }
188*1a96fba6SXin Li 
189*1a96fba6SXin Li     // Ignore file descriptors used by the PipeMap, they will be handled
190*1a96fba6SXin Li     // by this process later on.
191*1a96fba6SXin Li     if (IsFileDescriptorInPipeMap(fd)) {
192*1a96fba6SXin Li       continue;
193*1a96fba6SXin Li     }
194*1a96fba6SXin Li 
195*1a96fba6SXin Li     // Since we're just trying to close anything we can find,
196*1a96fba6SXin Li     // ignore any error return values of close().
197*1a96fba6SXin Li     IGNORE_EINTR(close(fd));
198*1a96fba6SXin Li   }
199*1a96fba6SXin Li }
200*1a96fba6SXin Li 
Start()201*1a96fba6SXin Li bool ProcessImpl::Start() {
202*1a96fba6SXin Li   // If no arguments are provided, fail.
203*1a96fba6SXin Li   if (arguments_.empty()) {
204*1a96fba6SXin Li     return false;
205*1a96fba6SXin Li   }
206*1a96fba6SXin Li   std::unique_ptr<char*[]> argv =
207*1a96fba6SXin Li       std::make_unique<char*[]>(arguments_.size() + 1);
208*1a96fba6SXin Li 
209*1a96fba6SXin Li   for (size_t i = 0; i < arguments_.size(); ++i)
210*1a96fba6SXin Li     argv[i] = const_cast<char*>(arguments_[i].c_str());
211*1a96fba6SXin Li 
212*1a96fba6SXin Li   argv[arguments_.size()] = nullptr;
213*1a96fba6SXin Li 
214*1a96fba6SXin Li   if (!PopulatePipeMap()) {
215*1a96fba6SXin Li     LOG(ERROR) << "Failing to start because pipe creation failed";
216*1a96fba6SXin Li     return false;
217*1a96fba6SXin Li   }
218*1a96fba6SXin Li 
219*1a96fba6SXin Li   // 64K child stack size
220*1a96fba6SXin Li   constexpr size_t kStackSize = 64 * 1024;
221*1a96fba6SXin Li   // clone() expects a pointer which points to top most byte of the stack
222*1a96fba6SXin Li   auto stack = reinterpret_cast<char*>(mmap(nullptr,
223*1a96fba6SXin Li                                             kStackSize,
224*1a96fba6SXin Li                                             PROT_READ | PROT_WRITE,
225*1a96fba6SXin Li                                             MAP_ANON | MAP_PRIVATE,
226*1a96fba6SXin Li                                             -1,
227*1a96fba6SXin Li                                             0)) +
228*1a96fba6SXin Li                kStackSize;
229*1a96fba6SXin Li   struct State {
230*1a96fba6SXin Li     ProcessImpl* p;
231*1a96fba6SXin Li     char** argv;
232*1a96fba6SXin Li   } state{};
233*1a96fba6SXin Li   state.p = this;
234*1a96fba6SXin Li   state.argv = argv.get();
235*1a96fba6SXin Li   int flags = SIGCHLD;
236*1a96fba6SXin Li   if (enter_new_pid_namespace_) {
237*1a96fba6SXin Li     flags |= CLONE_NEWPID;
238*1a96fba6SXin Li   }
239*1a96fba6SXin Li   int pid = clone(
240*1a96fba6SXin Li       [](void* arg) {
241*1a96fba6SXin Li         State* s = reinterpret_cast<State*>(arg);
242*1a96fba6SXin Li         s->p->ExecChildProcess(s->argv);
243*1a96fba6SXin Li         return 0;
244*1a96fba6SXin Li       },
245*1a96fba6SXin Li       stack,
246*1a96fba6SXin Li       flags,
247*1a96fba6SXin Li       &state);
248*1a96fba6SXin Li 
249*1a96fba6SXin Li   // Still executing inside the parent process with known child pid.
250*1a96fba6SXin Li   arguments_.clear();
251*1a96fba6SXin Li   UpdatePid(pid);
252*1a96fba6SXin Li   // Close our copy of child side pipes only if we created those pipes.
253*1a96fba6SXin Li   for (const auto& i : pipe_map_) {
254*1a96fba6SXin Li     if (!i.second.is_bound_) {
255*1a96fba6SXin Li       IGNORE_EINTR(close(i.second.child_fd_));
256*1a96fba6SXin Li     }
257*1a96fba6SXin Li   }
258*1a96fba6SXin Li   return true;
259*1a96fba6SXin Li }
260*1a96fba6SXin Li 
ExecChildProcess(char ** argv)261*1a96fba6SXin Li void ProcessImpl::ExecChildProcess(char** argv) {
262*1a96fba6SXin Li #ifdef __BIONIC__
263*1a96fba6SXin Li   // Disable fdsan and fdtrack post-fork, so we don't falsely trigger on
264*1a96fba6SXin Li   // processes that fork, close all of their fds, and then exec.
265*1a96fba6SXin Li   android_fdsan_set_error_level(ANDROID_FDSAN_ERROR_LEVEL_DISABLED);
266*1a96fba6SXin Li #endif
267*1a96fba6SXin Li   // Executing inside the child process.
268*1a96fba6SXin Li   // Close unused file descriptors.
269*1a96fba6SXin Li   if (close_unused_file_descriptors_) {
270*1a96fba6SXin Li     CloseUnusedFileDescriptors();
271*1a96fba6SXin Li   }
272*1a96fba6SXin Li 
273*1a96fba6SXin Li   base::InjectiveMultimap fd_shuffle;
274*1a96fba6SXin Li   for (const auto& it : pipe_map_) {
275*1a96fba6SXin Li     // Close parent's side of the child pipes.
276*1a96fba6SXin Li     if (it.second.parent_fd_ != -1)
277*1a96fba6SXin Li       IGNORE_EINTR(close(it.second.parent_fd_));
278*1a96fba6SXin Li 
279*1a96fba6SXin Li     fd_shuffle.emplace_back(it.second.child_fd_, it.first, true);
280*1a96fba6SXin Li   }
281*1a96fba6SXin Li 
282*1a96fba6SXin Li   if (!base::ShuffleFileDescriptors(&fd_shuffle)) {
283*1a96fba6SXin Li     PLOG(ERROR) << "Could not shuffle file descriptors";
284*1a96fba6SXin Li     _exit(kErrorExitStatus);
285*1a96fba6SXin Li   }
286*1a96fba6SXin Li 
287*1a96fba6SXin Li   if (!input_file_.empty()) {
288*1a96fba6SXin Li     int input_handle = HANDLE_EINTR(
289*1a96fba6SXin Li         open(input_file_.c_str(), O_RDONLY | O_NOFOLLOW | O_NOCTTY));
290*1a96fba6SXin Li     if (input_handle < 0) {
291*1a96fba6SXin Li       PLOG(ERROR) << "Could not open " << input_file_;
292*1a96fba6SXin Li       // Avoid exit() to avoid atexit handlers from parent.
293*1a96fba6SXin Li       _exit(kErrorExitStatus);
294*1a96fba6SXin Li     }
295*1a96fba6SXin Li 
296*1a96fba6SXin Li     // It's possible input_handle is already stdin. But if not, we need
297*1a96fba6SXin Li     // to dup into that file descriptor and close the original.
298*1a96fba6SXin Li     if (input_handle != STDIN_FILENO) {
299*1a96fba6SXin Li       if (HANDLE_EINTR(dup2(input_handle, STDIN_FILENO)) < 0) {
300*1a96fba6SXin Li         PLOG(ERROR) << "Could not dup fd to stdin for " << input_file_;
301*1a96fba6SXin Li         _exit(kErrorExitStatus);
302*1a96fba6SXin Li       }
303*1a96fba6SXin Li       IGNORE_EINTR(close(input_handle));
304*1a96fba6SXin Li     }
305*1a96fba6SXin Li   }
306*1a96fba6SXin Li 
307*1a96fba6SXin Li   if (!output_file_.empty()) {
308*1a96fba6SXin Li     int output_handle = HANDLE_EINTR(open(
309*1a96fba6SXin Li         output_file_.c_str(), O_CREAT | O_WRONLY | O_TRUNC | O_NOFOLLOW, 0666));
310*1a96fba6SXin Li     if (output_handle < 0) {
311*1a96fba6SXin Li       PLOG(ERROR) << "Could not create " << output_file_;
312*1a96fba6SXin Li       // Avoid exit() to avoid atexit handlers from parent.
313*1a96fba6SXin Li       _exit(kErrorExitStatus);
314*1a96fba6SXin Li     }
315*1a96fba6SXin Li     HANDLE_EINTR(dup2(output_handle, STDOUT_FILENO));
316*1a96fba6SXin Li     HANDLE_EINTR(dup2(output_handle, STDERR_FILENO));
317*1a96fba6SXin Li     // Only close output_handle if it does not happen to be one of
318*1a96fba6SXin Li     // the two standard file descriptors we are trying to redirect.
319*1a96fba6SXin Li     if (output_handle != STDOUT_FILENO && output_handle != STDERR_FILENO) {
320*1a96fba6SXin Li       IGNORE_EINTR(close(output_handle));
321*1a96fba6SXin Li     }
322*1a96fba6SXin Li   }
323*1a96fba6SXin Li   if (gid_ != static_cast<gid_t>(-1) && setresgid(gid_, gid_, gid_) < 0) {
324*1a96fba6SXin Li     int saved_errno = errno;
325*1a96fba6SXin Li     LOG(ERROR) << "Unable to set GID to " << gid_ << ": " << saved_errno;
326*1a96fba6SXin Li     _exit(kErrorExitStatus);
327*1a96fba6SXin Li   }
328*1a96fba6SXin Li   if (uid_ != static_cast<uid_t>(-1) && setresuid(uid_, uid_, uid_) < 0) {
329*1a96fba6SXin Li     int saved_errno = errno;
330*1a96fba6SXin Li     LOG(ERROR) << "Unable to set UID to " << uid_ << ": " << saved_errno;
331*1a96fba6SXin Li     _exit(kErrorExitStatus);
332*1a96fba6SXin Li   }
333*1a96fba6SXin Li   if (!pre_exec_.Run()) {
334*1a96fba6SXin Li     LOG(ERROR) << "Pre-exec callback failed";
335*1a96fba6SXin Li     _exit(kErrorExitStatus);
336*1a96fba6SXin Li   }
337*1a96fba6SXin Li   // Reset signal mask for the child process if not inheriting signal mask
338*1a96fba6SXin Li   // from the parent process.
339*1a96fba6SXin Li   if (!inherit_parent_signal_mask_) {
340*1a96fba6SXin Li     sigset_t signal_mask;
341*1a96fba6SXin Li     CHECK_EQ(0, sigemptyset(&signal_mask));
342*1a96fba6SXin Li     CHECK_EQ(0, sigprocmask(SIG_SETMASK, &signal_mask, nullptr));
343*1a96fba6SXin Li   }
344*1a96fba6SXin Li   if (search_path_) {
345*1a96fba6SXin Li     execvp(argv[0], &argv[0]);
346*1a96fba6SXin Li   } else {
347*1a96fba6SXin Li     execv(argv[0], &argv[0]);
348*1a96fba6SXin Li   }
349*1a96fba6SXin Li   PLOG(ERROR) << "Exec of " << argv[0] << " failed";
350*1a96fba6SXin Li   _exit(kErrorExitStatus);
351*1a96fba6SXin Li }
352*1a96fba6SXin Li 
Wait()353*1a96fba6SXin Li int ProcessImpl::Wait() {
354*1a96fba6SXin Li   int status = 0;
355*1a96fba6SXin Li   if (pid_ == 0) {
356*1a96fba6SXin Li     LOG(ERROR) << "Process not running";
357*1a96fba6SXin Li     return -1;
358*1a96fba6SXin Li   }
359*1a96fba6SXin Li   if (HANDLE_EINTR(waitpid(pid_, &status, 0)) < 0) {
360*1a96fba6SXin Li     int saved_errno = errno;
361*1a96fba6SXin Li     LOG(ERROR) << "Problem waiting for pid " << pid_ << ": " << saved_errno;
362*1a96fba6SXin Li     return -1;
363*1a96fba6SXin Li   }
364*1a96fba6SXin Li   pid_t old_pid = pid_;
365*1a96fba6SXin Li   // Update the pid to 0 - do not Reset as we do not want to try to
366*1a96fba6SXin Li   // kill the process that has just exited.
367*1a96fba6SXin Li   UpdatePid(0);
368*1a96fba6SXin Li   if (!WIFEXITED(status)) {
369*1a96fba6SXin Li     DCHECK(WIFSIGNALED(status))
370*1a96fba6SXin Li         << old_pid << " neither exited, nor died on a signal?";
371*1a96fba6SXin Li     LOG(ERROR) << "Process " << old_pid
372*1a96fba6SXin Li                << " did not exit normally: " << WTERMSIG(status);
373*1a96fba6SXin Li     return -1;
374*1a96fba6SXin Li   }
375*1a96fba6SXin Li   return WEXITSTATUS(status);
376*1a96fba6SXin Li }
377*1a96fba6SXin Li 
Run()378*1a96fba6SXin Li int ProcessImpl::Run() {
379*1a96fba6SXin Li   if (!Start()) {
380*1a96fba6SXin Li     return -1;
381*1a96fba6SXin Li   }
382*1a96fba6SXin Li   return Wait();
383*1a96fba6SXin Li }
384*1a96fba6SXin Li 
pid()385*1a96fba6SXin Li pid_t ProcessImpl::pid() {
386*1a96fba6SXin Li   return pid_;
387*1a96fba6SXin Li }
388*1a96fba6SXin Li 
Kill(int signal,int timeout)389*1a96fba6SXin Li bool ProcessImpl::Kill(int signal, int timeout) {
390*1a96fba6SXin Li   if (pid_ == 0) {
391*1a96fba6SXin Li     // Passing pid == 0 to kill is committing suicide.  Check specifically.
392*1a96fba6SXin Li     LOG(ERROR) << "Process not running";
393*1a96fba6SXin Li     return false;
394*1a96fba6SXin Li   }
395*1a96fba6SXin Li   if (kill(pid_, signal) < 0) {
396*1a96fba6SXin Li     PLOG(ERROR) << "Unable to send signal to " << pid_;
397*1a96fba6SXin Li     return false;
398*1a96fba6SXin Li   }
399*1a96fba6SXin Li   base::TimeTicks start_signal = base::TimeTicks::Now();
400*1a96fba6SXin Li   do {
401*1a96fba6SXin Li     int status = 0;
402*1a96fba6SXin Li     pid_t w = waitpid(pid_, &status, WNOHANG);
403*1a96fba6SXin Li     if (w < 0) {
404*1a96fba6SXin Li       if (errno == ECHILD)
405*1a96fba6SXin Li         return true;
406*1a96fba6SXin Li       PLOG(ERROR) << "Waitpid returned " << w;
407*1a96fba6SXin Li       return false;
408*1a96fba6SXin Li     }
409*1a96fba6SXin Li     if (w > 0) {
410*1a96fba6SXin Li       Reset(0);
411*1a96fba6SXin Li       return true;
412*1a96fba6SXin Li     }
413*1a96fba6SXin Li     usleep(100);
414*1a96fba6SXin Li   } while ((base::TimeTicks::Now() - start_signal).InSecondsF() <= timeout);
415*1a96fba6SXin Li   LOG(INFO) << "process " << pid_ << " did not exit from signal " << signal
416*1a96fba6SXin Li             << " in " << timeout << " seconds";
417*1a96fba6SXin Li   return false;
418*1a96fba6SXin Li }
419*1a96fba6SXin Li 
UpdatePid(pid_t new_pid)420*1a96fba6SXin Li void ProcessImpl::UpdatePid(pid_t new_pid) {
421*1a96fba6SXin Li   pid_ = new_pid;
422*1a96fba6SXin Li }
423*1a96fba6SXin Li 
Reset(pid_t new_pid)424*1a96fba6SXin Li void ProcessImpl::Reset(pid_t new_pid) {
425*1a96fba6SXin Li   arguments_.clear();
426*1a96fba6SXin Li   // Close our side of all pipes to this child giving the child to
427*1a96fba6SXin Li   // handle sigpipes and shutdown nicely, though likely it won't
428*1a96fba6SXin Li   // have time.
429*1a96fba6SXin Li   for (PipeMap::iterator i = pipe_map_.begin(); i != pipe_map_.end(); ++i)
430*1a96fba6SXin Li     IGNORE_EINTR(close(i->second.parent_fd_));
431*1a96fba6SXin Li   pipe_map_.clear();
432*1a96fba6SXin Li   if (pid_)
433*1a96fba6SXin Li     Kill(SIGKILL, 0);
434*1a96fba6SXin Li   UpdatePid(new_pid);
435*1a96fba6SXin Li }
436*1a96fba6SXin Li 
ResetPidByFile(const std::string & pid_file)437*1a96fba6SXin Li bool ProcessImpl::ResetPidByFile(const std::string& pid_file) {
438*1a96fba6SXin Li   std::string contents;
439*1a96fba6SXin Li   if (!base::ReadFileToString(base::FilePath(pid_file), &contents)) {
440*1a96fba6SXin Li     LOG(ERROR) << "Could not read pid file" << pid_file;
441*1a96fba6SXin Li     return false;
442*1a96fba6SXin Li   }
443*1a96fba6SXin Li   base::TrimWhitespaceASCII(contents, base::TRIM_TRAILING, &contents);
444*1a96fba6SXin Li   int64_t pid_int64 = 0;
445*1a96fba6SXin Li   if (!base::StringToInt64(contents, &pid_int64)) {
446*1a96fba6SXin Li     LOG(ERROR) << "Unexpected pid file contents";
447*1a96fba6SXin Li     return false;
448*1a96fba6SXin Li   }
449*1a96fba6SXin Li   Reset(pid_int64);
450*1a96fba6SXin Li   return true;
451*1a96fba6SXin Li }
452*1a96fba6SXin Li 
Release()453*1a96fba6SXin Li pid_t ProcessImpl::Release() {
454*1a96fba6SXin Li   pid_t old_pid = pid_;
455*1a96fba6SXin Li   pid_ = 0;
456*1a96fba6SXin Li   return old_pid;
457*1a96fba6SXin Li }
458*1a96fba6SXin Li 
459*1a96fba6SXin Li }  // namespace brillo
460