process_posix.cc 11 KB

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