xref: /aosp_15_r20/external/libchrome/base/process/process_posix.cc (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
1*635a8641SAndroid Build Coastguard Worker // Copyright 2011 The Chromium Authors. All rights reserved.
2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file.
4*635a8641SAndroid Build Coastguard Worker 
5*635a8641SAndroid Build Coastguard Worker #include "base/process/process.h"
6*635a8641SAndroid Build Coastguard Worker 
7*635a8641SAndroid Build Coastguard Worker #include <errno.h>
8*635a8641SAndroid Build Coastguard Worker #include <signal.h>
9*635a8641SAndroid Build Coastguard Worker #include <stdint.h>
10*635a8641SAndroid Build Coastguard Worker #include <sys/resource.h>
11*635a8641SAndroid Build Coastguard Worker #include <sys/wait.h>
12*635a8641SAndroid Build Coastguard Worker 
13*635a8641SAndroid Build Coastguard Worker #include "base/debug/activity_tracker.h"
14*635a8641SAndroid Build Coastguard Worker #include "base/files/scoped_file.h"
15*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
16*635a8641SAndroid Build Coastguard Worker #include "base/posix/eintr_wrapper.h"
17*635a8641SAndroid Build Coastguard Worker #include "base/process/kill.h"
18*635a8641SAndroid Build Coastguard Worker #include "base/threading/thread_restrictions.h"
19*635a8641SAndroid Build Coastguard Worker #include "build/build_config.h"
20*635a8641SAndroid Build Coastguard Worker 
21*635a8641SAndroid Build Coastguard Worker #if defined(OS_MACOSX)
22*635a8641SAndroid Build Coastguard Worker #include <sys/event.h>
23*635a8641SAndroid Build Coastguard Worker #endif
24*635a8641SAndroid Build Coastguard Worker 
25*635a8641SAndroid Build Coastguard Worker namespace {
26*635a8641SAndroid Build Coastguard Worker 
27*635a8641SAndroid Build Coastguard Worker #if !defined(OS_NACL_NONSFI)
28*635a8641SAndroid Build Coastguard Worker 
WaitpidWithTimeout(base::ProcessHandle handle,int * status,base::TimeDelta wait)29*635a8641SAndroid Build Coastguard Worker bool WaitpidWithTimeout(base::ProcessHandle handle,
30*635a8641SAndroid Build Coastguard Worker                         int* status,
31*635a8641SAndroid Build Coastguard Worker                         base::TimeDelta wait) {
32*635a8641SAndroid Build Coastguard Worker   // This POSIX version of this function only guarantees that we wait no less
33*635a8641SAndroid Build Coastguard Worker   // than |wait| for the process to exit.  The child process may
34*635a8641SAndroid Build Coastguard Worker   // exit sometime before the timeout has ended but we may still block for up
35*635a8641SAndroid Build Coastguard Worker   // to 256 milliseconds after the fact.
36*635a8641SAndroid Build Coastguard Worker   //
37*635a8641SAndroid Build Coastguard Worker   // waitpid() has no direct support on POSIX for specifying a timeout, you can
38*635a8641SAndroid Build Coastguard Worker   // either ask it to block indefinitely or return immediately (WNOHANG).
39*635a8641SAndroid Build Coastguard Worker   // When a child process terminates a SIGCHLD signal is sent to the parent.
40*635a8641SAndroid Build Coastguard Worker   // Catching this signal would involve installing a signal handler which may
41*635a8641SAndroid Build Coastguard Worker   // affect other parts of the application and would be difficult to debug.
42*635a8641SAndroid Build Coastguard Worker   //
43*635a8641SAndroid Build Coastguard Worker   // Our strategy is to call waitpid() once up front to check if the process
44*635a8641SAndroid Build Coastguard Worker   // has already exited, otherwise to loop for |wait|, sleeping for
45*635a8641SAndroid Build Coastguard Worker   // at most 256 milliseconds each time using usleep() and then calling
46*635a8641SAndroid Build Coastguard Worker   // waitpid().  The amount of time we sleep starts out at 1 milliseconds, and
47*635a8641SAndroid Build Coastguard Worker   // we double it every 4 sleep cycles.
48*635a8641SAndroid Build Coastguard Worker   //
49*635a8641SAndroid Build Coastguard Worker   // usleep() is speced to exit if a signal is received for which a handler
50*635a8641SAndroid Build Coastguard Worker   // has been installed.  This means that when a SIGCHLD is sent, it will exit
51*635a8641SAndroid Build Coastguard Worker   // depending on behavior external to this function.
52*635a8641SAndroid Build Coastguard Worker   //
53*635a8641SAndroid Build Coastguard Worker   // This function is used primarily for unit tests, if we want to use it in
54*635a8641SAndroid Build Coastguard Worker   // the application itself it would probably be best to examine other routes.
55*635a8641SAndroid Build Coastguard Worker 
56*635a8641SAndroid Build Coastguard Worker   if (wait == base::TimeDelta::Max()) {
57*635a8641SAndroid Build Coastguard Worker     return HANDLE_EINTR(waitpid(handle, status, 0)) > 0;
58*635a8641SAndroid Build Coastguard Worker   }
59*635a8641SAndroid Build Coastguard Worker 
60*635a8641SAndroid Build Coastguard Worker   pid_t ret_pid = HANDLE_EINTR(waitpid(handle, status, WNOHANG));
61*635a8641SAndroid Build Coastguard Worker   static const int64_t kMaxSleepInMicroseconds = 1 << 18;  // ~256 milliseconds.
62*635a8641SAndroid Build Coastguard Worker   int64_t max_sleep_time_usecs = 1 << 10;                  // ~1 milliseconds.
63*635a8641SAndroid Build Coastguard Worker   int64_t double_sleep_time = 0;
64*635a8641SAndroid Build Coastguard Worker 
65*635a8641SAndroid Build Coastguard Worker   // If the process hasn't exited yet, then sleep and try again.
66*635a8641SAndroid Build Coastguard Worker   base::TimeTicks wakeup_time = base::TimeTicks::Now() + wait;
67*635a8641SAndroid Build Coastguard Worker   while (ret_pid == 0) {
68*635a8641SAndroid Build Coastguard Worker     base::TimeTicks now = base::TimeTicks::Now();
69*635a8641SAndroid Build Coastguard Worker     if (now > wakeup_time)
70*635a8641SAndroid Build Coastguard Worker       break;
71*635a8641SAndroid Build Coastguard Worker     // Guaranteed to be non-negative!
72*635a8641SAndroid Build Coastguard Worker     int64_t sleep_time_usecs = (wakeup_time - now).InMicroseconds();
73*635a8641SAndroid Build Coastguard Worker     // Sleep for a bit while we wait for the process to finish.
74*635a8641SAndroid Build Coastguard Worker     if (sleep_time_usecs > max_sleep_time_usecs)
75*635a8641SAndroid Build Coastguard Worker       sleep_time_usecs = max_sleep_time_usecs;
76*635a8641SAndroid Build Coastguard Worker 
77*635a8641SAndroid Build Coastguard Worker     // usleep() will return 0 and set errno to EINTR on receipt of a signal
78*635a8641SAndroid Build Coastguard Worker     // such as SIGCHLD.
79*635a8641SAndroid Build Coastguard Worker     usleep(sleep_time_usecs);
80*635a8641SAndroid Build Coastguard Worker     ret_pid = HANDLE_EINTR(waitpid(handle, status, WNOHANG));
81*635a8641SAndroid Build Coastguard Worker 
82*635a8641SAndroid Build Coastguard Worker     if ((max_sleep_time_usecs < kMaxSleepInMicroseconds) &&
83*635a8641SAndroid Build Coastguard Worker         (double_sleep_time++ % 4 == 0)) {
84*635a8641SAndroid Build Coastguard Worker       max_sleep_time_usecs *= 2;
85*635a8641SAndroid Build Coastguard Worker     }
86*635a8641SAndroid Build Coastguard Worker   }
87*635a8641SAndroid Build Coastguard Worker 
88*635a8641SAndroid Build Coastguard Worker   return ret_pid > 0;
89*635a8641SAndroid Build Coastguard Worker }
90*635a8641SAndroid Build Coastguard Worker 
91*635a8641SAndroid Build Coastguard Worker #if defined(OS_MACOSX)
92*635a8641SAndroid Build Coastguard Worker // Using kqueue on Mac so that we can wait on non-child processes.
93*635a8641SAndroid Build Coastguard Worker // We can't use kqueues on child processes because we need to reap
94*635a8641SAndroid Build Coastguard Worker // our own children using wait.
WaitForSingleNonChildProcess(base::ProcessHandle handle,base::TimeDelta wait)95*635a8641SAndroid Build Coastguard Worker bool WaitForSingleNonChildProcess(base::ProcessHandle handle,
96*635a8641SAndroid Build Coastguard Worker                                   base::TimeDelta wait) {
97*635a8641SAndroid Build Coastguard Worker   DCHECK_GT(handle, 0);
98*635a8641SAndroid Build Coastguard Worker 
99*635a8641SAndroid Build Coastguard Worker   base::ScopedFD kq(kqueue());
100*635a8641SAndroid Build Coastguard Worker   if (!kq.is_valid()) {
101*635a8641SAndroid Build Coastguard Worker     DPLOG(ERROR) << "kqueue";
102*635a8641SAndroid Build Coastguard Worker     return false;
103*635a8641SAndroid Build Coastguard Worker   }
104*635a8641SAndroid Build Coastguard Worker 
105*635a8641SAndroid Build Coastguard Worker   struct kevent change = {0};
106*635a8641SAndroid Build Coastguard Worker   EV_SET(&change, handle, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL);
107*635a8641SAndroid Build Coastguard Worker   int result = HANDLE_EINTR(kevent(kq.get(), &change, 1, NULL, 0, NULL));
108*635a8641SAndroid Build Coastguard Worker   if (result == -1) {
109*635a8641SAndroid Build Coastguard Worker     if (errno == ESRCH) {
110*635a8641SAndroid Build Coastguard Worker       // If the process wasn't found, it must be dead.
111*635a8641SAndroid Build Coastguard Worker       return true;
112*635a8641SAndroid Build Coastguard Worker     }
113*635a8641SAndroid Build Coastguard Worker 
114*635a8641SAndroid Build Coastguard Worker     DPLOG(ERROR) << "kevent (setup " << handle << ")";
115*635a8641SAndroid Build Coastguard Worker     return false;
116*635a8641SAndroid Build Coastguard Worker   }
117*635a8641SAndroid Build Coastguard Worker 
118*635a8641SAndroid Build Coastguard Worker   // Keep track of the elapsed time to be able to restart kevent if it's
119*635a8641SAndroid Build Coastguard Worker   // interrupted.
120*635a8641SAndroid Build Coastguard Worker   bool wait_forever = (wait == base::TimeDelta::Max());
121*635a8641SAndroid Build Coastguard Worker   base::TimeDelta remaining_delta;
122*635a8641SAndroid Build Coastguard Worker   base::TimeTicks deadline;
123*635a8641SAndroid Build Coastguard Worker   if (!wait_forever) {
124*635a8641SAndroid Build Coastguard Worker     remaining_delta = wait;
125*635a8641SAndroid Build Coastguard Worker     deadline = base::TimeTicks::Now() + remaining_delta;
126*635a8641SAndroid Build Coastguard Worker   }
127*635a8641SAndroid Build Coastguard Worker 
128*635a8641SAndroid Build Coastguard Worker   result = -1;
129*635a8641SAndroid Build Coastguard Worker   struct kevent event = {0};
130*635a8641SAndroid Build Coastguard Worker 
131*635a8641SAndroid Build Coastguard Worker   do {
132*635a8641SAndroid Build Coastguard Worker     struct timespec remaining_timespec;
133*635a8641SAndroid Build Coastguard Worker     struct timespec* remaining_timespec_ptr;
134*635a8641SAndroid Build Coastguard Worker     if (wait_forever) {
135*635a8641SAndroid Build Coastguard Worker       remaining_timespec_ptr = NULL;
136*635a8641SAndroid Build Coastguard Worker     } else {
137*635a8641SAndroid Build Coastguard Worker       remaining_timespec = remaining_delta.ToTimeSpec();
138*635a8641SAndroid Build Coastguard Worker       remaining_timespec_ptr = &remaining_timespec;
139*635a8641SAndroid Build Coastguard Worker     }
140*635a8641SAndroid Build Coastguard Worker 
141*635a8641SAndroid Build Coastguard Worker     result = kevent(kq.get(), NULL, 0, &event, 1, remaining_timespec_ptr);
142*635a8641SAndroid Build Coastguard Worker 
143*635a8641SAndroid Build Coastguard Worker     if (result == -1 && errno == EINTR) {
144*635a8641SAndroid Build Coastguard Worker       if (!wait_forever) {
145*635a8641SAndroid Build Coastguard Worker         remaining_delta = deadline - base::TimeTicks::Now();
146*635a8641SAndroid Build Coastguard Worker       }
147*635a8641SAndroid Build Coastguard Worker       result = 0;
148*635a8641SAndroid Build Coastguard Worker     } else {
149*635a8641SAndroid Build Coastguard Worker       break;
150*635a8641SAndroid Build Coastguard Worker     }
151*635a8641SAndroid Build Coastguard Worker   } while (wait_forever || remaining_delta > base::TimeDelta());
152*635a8641SAndroid Build Coastguard Worker 
153*635a8641SAndroid Build Coastguard Worker   if (result < 0) {
154*635a8641SAndroid Build Coastguard Worker     DPLOG(ERROR) << "kevent (wait " << handle << ")";
155*635a8641SAndroid Build Coastguard Worker     return false;
156*635a8641SAndroid Build Coastguard Worker   } else if (result > 1) {
157*635a8641SAndroid Build Coastguard Worker     DLOG(ERROR) << "kevent (wait " << handle << "): unexpected result "
158*635a8641SAndroid Build Coastguard Worker                 << result;
159*635a8641SAndroid Build Coastguard Worker     return false;
160*635a8641SAndroid Build Coastguard Worker   } else if (result == 0) {
161*635a8641SAndroid Build Coastguard Worker     // Timed out.
162*635a8641SAndroid Build Coastguard Worker     return false;
163*635a8641SAndroid Build Coastguard Worker   }
164*635a8641SAndroid Build Coastguard Worker 
165*635a8641SAndroid Build Coastguard Worker   DCHECK_EQ(result, 1);
166*635a8641SAndroid Build Coastguard Worker 
167*635a8641SAndroid Build Coastguard Worker   if (event.filter != EVFILT_PROC ||
168*635a8641SAndroid Build Coastguard Worker       (event.fflags & NOTE_EXIT) == 0 ||
169*635a8641SAndroid Build Coastguard Worker       event.ident != static_cast<uintptr_t>(handle)) {
170*635a8641SAndroid Build Coastguard Worker     DLOG(ERROR) << "kevent (wait " << handle
171*635a8641SAndroid Build Coastguard Worker                 << "): unexpected event: filter=" << event.filter
172*635a8641SAndroid Build Coastguard Worker                 << ", fflags=" << event.fflags
173*635a8641SAndroid Build Coastguard Worker                 << ", ident=" << event.ident;
174*635a8641SAndroid Build Coastguard Worker     return false;
175*635a8641SAndroid Build Coastguard Worker   }
176*635a8641SAndroid Build Coastguard Worker 
177*635a8641SAndroid Build Coastguard Worker   return true;
178*635a8641SAndroid Build Coastguard Worker }
179*635a8641SAndroid Build Coastguard Worker #endif  // OS_MACOSX
180*635a8641SAndroid Build Coastguard Worker 
WaitForExitWithTimeoutImpl(base::ProcessHandle handle,int * exit_code,base::TimeDelta timeout)181*635a8641SAndroid Build Coastguard Worker bool WaitForExitWithTimeoutImpl(base::ProcessHandle handle,
182*635a8641SAndroid Build Coastguard Worker                                 int* exit_code,
183*635a8641SAndroid Build Coastguard Worker                                 base::TimeDelta timeout) {
184*635a8641SAndroid Build Coastguard Worker   const base::ProcessHandle our_pid = base::GetCurrentProcessHandle();
185*635a8641SAndroid Build Coastguard Worker   if (handle == our_pid) {
186*635a8641SAndroid Build Coastguard Worker     // We won't be able to wait for ourselves to exit.
187*635a8641SAndroid Build Coastguard Worker     return false;
188*635a8641SAndroid Build Coastguard Worker   }
189*635a8641SAndroid Build Coastguard Worker 
190*635a8641SAndroid Build Coastguard Worker   const base::ProcessHandle parent_pid = base::GetParentProcessId(handle);
191*635a8641SAndroid Build Coastguard Worker   const bool exited = (parent_pid < 0);
192*635a8641SAndroid Build Coastguard Worker 
193*635a8641SAndroid Build Coastguard Worker   if (!exited && parent_pid != our_pid) {
194*635a8641SAndroid Build Coastguard Worker #if defined(OS_MACOSX)
195*635a8641SAndroid Build Coastguard Worker     // On Mac we can wait on non child processes.
196*635a8641SAndroid Build Coastguard Worker     return WaitForSingleNonChildProcess(handle, timeout);
197*635a8641SAndroid Build Coastguard Worker #else
198*635a8641SAndroid Build Coastguard Worker     // Currently on Linux we can't handle non child processes.
199*635a8641SAndroid Build Coastguard Worker     NOTIMPLEMENTED();
200*635a8641SAndroid Build Coastguard Worker #endif  // OS_MACOSX
201*635a8641SAndroid Build Coastguard Worker   }
202*635a8641SAndroid Build Coastguard Worker 
203*635a8641SAndroid Build Coastguard Worker   int status;
204*635a8641SAndroid Build Coastguard Worker   if (!WaitpidWithTimeout(handle, &status, timeout))
205*635a8641SAndroid Build Coastguard Worker     return exited;
206*635a8641SAndroid Build Coastguard Worker   if (WIFSIGNALED(status)) {
207*635a8641SAndroid Build Coastguard Worker     if (exit_code)
208*635a8641SAndroid Build Coastguard Worker       *exit_code = -1;
209*635a8641SAndroid Build Coastguard Worker     return true;
210*635a8641SAndroid Build Coastguard Worker   }
211*635a8641SAndroid Build Coastguard Worker   if (WIFEXITED(status)) {
212*635a8641SAndroid Build Coastguard Worker     if (exit_code)
213*635a8641SAndroid Build Coastguard Worker       *exit_code = WEXITSTATUS(status);
214*635a8641SAndroid Build Coastguard Worker     return true;
215*635a8641SAndroid Build Coastguard Worker   }
216*635a8641SAndroid Build Coastguard Worker   return exited;
217*635a8641SAndroid Build Coastguard Worker }
218*635a8641SAndroid Build Coastguard Worker #endif  // !defined(OS_NACL_NONSFI)
219*635a8641SAndroid Build Coastguard Worker 
220*635a8641SAndroid Build Coastguard Worker }  // namespace
221*635a8641SAndroid Build Coastguard Worker 
222*635a8641SAndroid Build Coastguard Worker namespace base {
223*635a8641SAndroid Build Coastguard Worker 
Process(ProcessHandle handle)224*635a8641SAndroid Build Coastguard Worker Process::Process(ProcessHandle handle) : process_(handle) {
225*635a8641SAndroid Build Coastguard Worker }
226*635a8641SAndroid Build Coastguard Worker 
227*635a8641SAndroid Build Coastguard Worker Process::~Process() = default;
228*635a8641SAndroid Build Coastguard Worker 
Process(Process && other)229*635a8641SAndroid Build Coastguard Worker Process::Process(Process&& other) : process_(other.process_) {
230*635a8641SAndroid Build Coastguard Worker   other.Close();
231*635a8641SAndroid Build Coastguard Worker }
232*635a8641SAndroid Build Coastguard Worker 
operator =(Process && other)233*635a8641SAndroid Build Coastguard Worker Process& Process::operator=(Process&& other) {
234*635a8641SAndroid Build Coastguard Worker   process_ = other.process_;
235*635a8641SAndroid Build Coastguard Worker   other.Close();
236*635a8641SAndroid Build Coastguard Worker   return *this;
237*635a8641SAndroid Build Coastguard Worker }
238*635a8641SAndroid Build Coastguard Worker 
239*635a8641SAndroid Build Coastguard Worker // static
Current()240*635a8641SAndroid Build Coastguard Worker Process Process::Current() {
241*635a8641SAndroid Build Coastguard Worker   return Process(GetCurrentProcessHandle());
242*635a8641SAndroid Build Coastguard Worker }
243*635a8641SAndroid Build Coastguard Worker 
244*635a8641SAndroid Build Coastguard Worker // static
Open(ProcessId pid)245*635a8641SAndroid Build Coastguard Worker Process Process::Open(ProcessId pid) {
246*635a8641SAndroid Build Coastguard Worker   if (pid == GetCurrentProcId())
247*635a8641SAndroid Build Coastguard Worker     return Current();
248*635a8641SAndroid Build Coastguard Worker 
249*635a8641SAndroid Build Coastguard Worker   // On POSIX process handles are the same as PIDs.
250*635a8641SAndroid Build Coastguard Worker   return Process(pid);
251*635a8641SAndroid Build Coastguard Worker }
252*635a8641SAndroid Build Coastguard Worker 
253*635a8641SAndroid Build Coastguard Worker // static
OpenWithExtraPrivileges(ProcessId pid)254*635a8641SAndroid Build Coastguard Worker Process Process::OpenWithExtraPrivileges(ProcessId pid) {
255*635a8641SAndroid Build Coastguard Worker   // On POSIX there are no privileges to set.
256*635a8641SAndroid Build Coastguard Worker   return Open(pid);
257*635a8641SAndroid Build Coastguard Worker }
258*635a8641SAndroid Build Coastguard Worker 
259*635a8641SAndroid Build Coastguard Worker // static
DeprecatedGetProcessFromHandle(ProcessHandle handle)260*635a8641SAndroid Build Coastguard Worker Process Process::DeprecatedGetProcessFromHandle(ProcessHandle handle) {
261*635a8641SAndroid Build Coastguard Worker   DCHECK_NE(handle, GetCurrentProcessHandle());
262*635a8641SAndroid Build Coastguard Worker   return Process(handle);
263*635a8641SAndroid Build Coastguard Worker }
264*635a8641SAndroid Build Coastguard Worker 
265*635a8641SAndroid Build Coastguard Worker #if !defined(OS_LINUX) && !defined(OS_MACOSX) && !defined(OS_AIX)
266*635a8641SAndroid Build Coastguard Worker // static
CanBackgroundProcesses()267*635a8641SAndroid Build Coastguard Worker bool Process::CanBackgroundProcesses() {
268*635a8641SAndroid Build Coastguard Worker   return false;
269*635a8641SAndroid Build Coastguard Worker }
270*635a8641SAndroid Build Coastguard Worker #endif  // !defined(OS_LINUX) && !defined(OS_MACOSX) && !defined(OS_AIX)
271*635a8641SAndroid Build Coastguard Worker 
272*635a8641SAndroid Build Coastguard Worker // static
TerminateCurrentProcessImmediately(int exit_code)273*635a8641SAndroid Build Coastguard Worker void Process::TerminateCurrentProcessImmediately(int exit_code) {
274*635a8641SAndroid Build Coastguard Worker   _exit(exit_code);
275*635a8641SAndroid Build Coastguard Worker }
276*635a8641SAndroid Build Coastguard Worker 
IsValid() const277*635a8641SAndroid Build Coastguard Worker bool Process::IsValid() const {
278*635a8641SAndroid Build Coastguard Worker   return process_ != kNullProcessHandle;
279*635a8641SAndroid Build Coastguard Worker }
280*635a8641SAndroid Build Coastguard Worker 
Handle() const281*635a8641SAndroid Build Coastguard Worker ProcessHandle Process::Handle() const {
282*635a8641SAndroid Build Coastguard Worker   return process_;
283*635a8641SAndroid Build Coastguard Worker }
284*635a8641SAndroid Build Coastguard Worker 
Duplicate() const285*635a8641SAndroid Build Coastguard Worker Process Process::Duplicate() const {
286*635a8641SAndroid Build Coastguard Worker   if (is_current())
287*635a8641SAndroid Build Coastguard Worker     return Current();
288*635a8641SAndroid Build Coastguard Worker 
289*635a8641SAndroid Build Coastguard Worker   return Process(process_);
290*635a8641SAndroid Build Coastguard Worker }
291*635a8641SAndroid Build Coastguard Worker 
Pid() const292*635a8641SAndroid Build Coastguard Worker ProcessId Process::Pid() const {
293*635a8641SAndroid Build Coastguard Worker   DCHECK(IsValid());
294*635a8641SAndroid Build Coastguard Worker   return GetProcId(process_);
295*635a8641SAndroid Build Coastguard Worker }
296*635a8641SAndroid Build Coastguard Worker 
is_current() const297*635a8641SAndroid Build Coastguard Worker bool Process::is_current() const {
298*635a8641SAndroid Build Coastguard Worker   return process_ == GetCurrentProcessHandle();
299*635a8641SAndroid Build Coastguard Worker }
300*635a8641SAndroid Build Coastguard Worker 
Close()301*635a8641SAndroid Build Coastguard Worker void Process::Close() {
302*635a8641SAndroid Build Coastguard Worker   process_ = kNullProcessHandle;
303*635a8641SAndroid Build Coastguard Worker   // if the process wasn't terminated (so we waited) or the state
304*635a8641SAndroid Build Coastguard Worker   // wasn't already collected w/ a wait from process_utils, we're gonna
305*635a8641SAndroid Build Coastguard Worker   // end up w/ a zombie when it does finally exit.
306*635a8641SAndroid Build Coastguard Worker }
307*635a8641SAndroid Build Coastguard Worker 
308*635a8641SAndroid Build Coastguard Worker #if !defined(OS_NACL_NONSFI)
Terminate(int exit_code,bool wait) const309*635a8641SAndroid Build Coastguard Worker bool Process::Terminate(int exit_code, bool wait) const {
310*635a8641SAndroid Build Coastguard Worker   // exit_code isn't supportable.
311*635a8641SAndroid Build Coastguard Worker   DCHECK(IsValid());
312*635a8641SAndroid Build Coastguard Worker   CHECK_GT(process_, 0);
313*635a8641SAndroid Build Coastguard Worker 
314*635a8641SAndroid Build Coastguard Worker   bool did_terminate = kill(process_, SIGTERM) == 0;
315*635a8641SAndroid Build Coastguard Worker 
316*635a8641SAndroid Build Coastguard Worker   if (wait && did_terminate) {
317*635a8641SAndroid Build Coastguard Worker     if (WaitForExitWithTimeout(TimeDelta::FromSeconds(60), nullptr))
318*635a8641SAndroid Build Coastguard Worker       return true;
319*635a8641SAndroid Build Coastguard Worker     did_terminate = kill(process_, SIGKILL) == 0;
320*635a8641SAndroid Build Coastguard Worker     if (did_terminate)
321*635a8641SAndroid Build Coastguard Worker       return WaitForExit(nullptr);
322*635a8641SAndroid Build Coastguard Worker   }
323*635a8641SAndroid Build Coastguard Worker 
324*635a8641SAndroid Build Coastguard Worker   if (!did_terminate)
325*635a8641SAndroid Build Coastguard Worker     DPLOG(ERROR) << "Unable to terminate process " << process_;
326*635a8641SAndroid Build Coastguard Worker 
327*635a8641SAndroid Build Coastguard Worker   return did_terminate;
328*635a8641SAndroid Build Coastguard Worker }
329*635a8641SAndroid Build Coastguard Worker #endif  // !defined(OS_NACL_NONSFI)
330*635a8641SAndroid Build Coastguard Worker 
WaitForExit(int * exit_code) const331*635a8641SAndroid Build Coastguard Worker bool Process::WaitForExit(int* exit_code) const {
332*635a8641SAndroid Build Coastguard Worker   return WaitForExitWithTimeout(TimeDelta::Max(), exit_code);
333*635a8641SAndroid Build Coastguard Worker }
334*635a8641SAndroid Build Coastguard Worker 
WaitForExitWithTimeout(TimeDelta timeout,int * exit_code) const335*635a8641SAndroid Build Coastguard Worker bool Process::WaitForExitWithTimeout(TimeDelta timeout, int* exit_code) const {
336*635a8641SAndroid Build Coastguard Worker   if (!timeout.is_zero())
337*635a8641SAndroid Build Coastguard Worker     internal::AssertBaseSyncPrimitivesAllowed();
338*635a8641SAndroid Build Coastguard Worker 
339*635a8641SAndroid Build Coastguard Worker   // Record the event that this thread is blocking upon (for hang diagnosis).
340*635a8641SAndroid Build Coastguard Worker   base::debug::ScopedProcessWaitActivity process_activity(this);
341*635a8641SAndroid Build Coastguard Worker 
342*635a8641SAndroid Build Coastguard Worker   int local_exit_code = 0;
343*635a8641SAndroid Build Coastguard Worker   bool exited = WaitForExitWithTimeoutImpl(Handle(), &local_exit_code, timeout);
344*635a8641SAndroid Build Coastguard Worker   if (exited) {
345*635a8641SAndroid Build Coastguard Worker     Exited(local_exit_code);
346*635a8641SAndroid Build Coastguard Worker     if (exit_code)
347*635a8641SAndroid Build Coastguard Worker       *exit_code = local_exit_code;
348*635a8641SAndroid Build Coastguard Worker   }
349*635a8641SAndroid Build Coastguard Worker   return exited;
350*635a8641SAndroid Build Coastguard Worker }
351*635a8641SAndroid Build Coastguard Worker 
Exited(int exit_code) const352*635a8641SAndroid Build Coastguard Worker void Process::Exited(int exit_code) const {}
353*635a8641SAndroid Build Coastguard Worker 
354*635a8641SAndroid Build Coastguard Worker #if !defined(OS_LINUX) && !defined(OS_MACOSX) && !defined(OS_AIX)
IsProcessBackgrounded() const355*635a8641SAndroid Build Coastguard Worker bool Process::IsProcessBackgrounded() const {
356*635a8641SAndroid Build Coastguard Worker   // See SetProcessBackgrounded().
357*635a8641SAndroid Build Coastguard Worker   DCHECK(IsValid());
358*635a8641SAndroid Build Coastguard Worker   return false;
359*635a8641SAndroid Build Coastguard Worker }
360*635a8641SAndroid Build Coastguard Worker 
SetProcessBackgrounded(bool value)361*635a8641SAndroid Build Coastguard Worker bool Process::SetProcessBackgrounded(bool value) {
362*635a8641SAndroid Build Coastguard Worker   // Not implemented for POSIX systems other than Linux and Mac. With POSIX, if
363*635a8641SAndroid Build Coastguard Worker   // we were to lower the process priority we wouldn't be able to raise it back
364*635a8641SAndroid Build Coastguard Worker   // to its initial priority.
365*635a8641SAndroid Build Coastguard Worker   NOTIMPLEMENTED();
366*635a8641SAndroid Build Coastguard Worker   return false;
367*635a8641SAndroid Build Coastguard Worker }
368*635a8641SAndroid Build Coastguard Worker #endif  // !defined(OS_LINUX) && !defined(OS_MACOSX) && !defined(OS_AIX)
369*635a8641SAndroid Build Coastguard Worker 
GetPriority() const370*635a8641SAndroid Build Coastguard Worker int Process::GetPriority() const {
371*635a8641SAndroid Build Coastguard Worker   DCHECK(IsValid());
372*635a8641SAndroid Build Coastguard Worker   return getpriority(PRIO_PROCESS, process_);
373*635a8641SAndroid Build Coastguard Worker }
374*635a8641SAndroid Build Coastguard Worker 
375*635a8641SAndroid Build Coastguard Worker }  // namespace base
376