#include "base/process/process.h"
#include <errno.h>
#include <signal.h>
#include <stdint.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <utility>
#include "base/clang_profiling_buildflags.h"
#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "base/notimplemented.h"
#include "base/posix/eintr_wrapper.h"
#include "base/process/kill.h"
#include "base/threading/thread_restrictions.h"
#include "base/time/time.h"
#include "base/trace_event/base_tracing.h"
#include "build/build_config.h"
#if BUILDFLAG(IS_MAC)
#include <sys/event.h>
#endif
#if BUILDFLAG(CLANG_PROFILING)
#include "base/test/clang_profiling.h"
#endif
#if BUILDFLAG(IS_IOS)
#include "TargetConditionals.h"
#endif
namespace {
#if !BUILDFLAG(IS_IOS) || (BUILDFLAG(IS_IOS) && TARGET_OS_SIMULATOR)
bool WaitpidWithTimeout(base::ProcessHandle handle,
int* status,
base::TimeDelta wait) { … }
#endif
#if BUILDFLAG(IS_MAC)
bool WaitForSingleNonChildProcess(base::ProcessHandle handle,
base::TimeDelta wait) {
DCHECK_GT(handle, 0);
base::ScopedFD kq(kqueue());
if (!kq.is_valid()) {
DPLOG(ERROR) << "kqueue";
return false;
}
struct kevent change = {0};
EV_SET(&change, handle, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL);
int result = HANDLE_EINTR(kevent(kq.get(), &change, 1, NULL, 0, NULL));
if (result == -1) {
if (errno == ESRCH) {
return true;
}
DPLOG(ERROR) << "kevent (setup " << handle << ")";
return false;
}
bool wait_forever = (wait == base::TimeDelta::Max());
base::TimeDelta remaining_delta;
base::TimeTicks deadline;
if (!wait_forever) {
remaining_delta = wait;
deadline = base::TimeTicks::Now() + remaining_delta;
}
result = -1;
struct kevent event = {0};
do {
struct timespec remaining_timespec;
struct timespec* remaining_timespec_ptr;
if (wait_forever) {
remaining_timespec_ptr = NULL;
} else {
remaining_timespec = remaining_delta.ToTimeSpec();
remaining_timespec_ptr = &remaining_timespec;
}
result = kevent(kq.get(), NULL, 0, &event, 1, remaining_timespec_ptr);
if (result == -1 && errno == EINTR) {
if (!wait_forever) {
remaining_delta = deadline - base::TimeTicks::Now();
}
result = 0;
} else {
break;
}
} while (wait_forever || remaining_delta.is_positive());
if (result < 0) {
DPLOG(ERROR) << "kevent (wait " << handle << ")";
return false;
} else if (result > 1) {
DLOG(ERROR) << "kevent (wait " << handle << "): unexpected result "
<< result;
return false;
} else if (result == 0) {
return false;
}
DCHECK_EQ(result, 1);
if (event.filter != EVFILT_PROC ||
(event.fflags & NOTE_EXIT) == 0 ||
event.ident != static_cast<uintptr_t>(handle)) {
DLOG(ERROR) << "kevent (wait " << handle
<< "): unexpected event: filter=" << event.filter
<< ", fflags=" << event.fflags
<< ", ident=" << event.ident;
return false;
}
return true;
}
#endif
}
namespace base {
Process::Process(ProcessHandle handle) : … { … }
Process::Process(Process&& other) : … { … }
Process& Process::operator=(Process&& other) { … }
Process::~Process() = default;
Process Process::Current() { … }
Process Process::Open(ProcessId pid) { … }
Process Process::OpenWithExtraPrivileges(ProcessId pid) { … }
void Process::TerminateCurrentProcessImmediately(int exit_code) { … }
bool Process::IsValid() const { … }
ProcessHandle Process::Handle() const { … }
Process Process::Duplicate() const { … }
ProcessHandle Process::Release() { … }
ProcessId Process::Pid() const { … }
bool Process::is_current() const { … }
void Process::Close() { … }
#if !BUILDFLAG(IS_IOS)
bool Process::Terminate(int exit_code, bool wait) const { … }
#endif
#if !BUILDFLAG(IS_IOS) || (BUILDFLAG(USE_BLINK) && TARGET_OS_SIMULATOR)
bool Process::TerminateInternal(int exit_code, bool wait) const { … }
#endif
bool Process::WaitForExit(int* exit_code) const { … }
#if !BUILDFLAG(IS_IOS)
bool Process::WaitForExitWithTimeout(TimeDelta timeout, int* exit_code) const { … }
#endif
#if !BUILDFLAG(IS_IOS) || (BUILDFLAG(USE_BLINK) && TARGET_OS_SIMULATOR)
bool Process::WaitForExitWithTimeoutImpl(base::ProcessHandle handle,
int* exit_code,
base::TimeDelta timeout) const { … }
#endif
void Process::Exited(int exit_code) const { … }
int Process::GetOSPriority() const { … }
}