Disable crashing tests, my previous checkin to mark them flaky did not help.
[chromium-blink-merge.git] / base / process_util_posix.cc
blob1ea90c3dd4fb844cfa9e37a6a387a0a3400a815a
1 // Copyright (c) 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.
5 #include <dirent.h>
6 #include <errno.h>
7 #include <fcntl.h>
8 #include <signal.h>
9 #include <stdlib.h>
10 #include <sys/resource.h>
11 #include <sys/time.h>
12 #include <sys/types.h>
13 #include <sys/wait.h>
14 #include <unistd.h>
16 #include <limits>
17 #include <set>
19 #include "base/command_line.h"
20 #include "base/compiler_specific.h"
21 #include "base/debug/stack_trace.h"
22 #include "base/dir_reader_posix.h"
23 #include "base/eintr_wrapper.h"
24 #include "base/file_util.h"
25 #include "base/logging.h"
26 #include "base/memory/scoped_ptr.h"
27 #include "base/process_util.h"
28 #include "base/stringprintf.h"
29 #include "base/synchronization/waitable_event.h"
30 #include "base/threading/platform_thread.h"
31 #include "base/threading/thread_restrictions.h"
32 #include "base/time.h"
34 #if defined(OS_MACOSX)
35 #include <crt_externs.h>
36 #include <sys/event.h>
37 #define environ (*_NSGetEnviron())
38 #else
39 extern char** environ;
40 #endif
42 namespace base {
44 namespace {
46 int WaitpidWithTimeout(ProcessHandle handle, int64 wait_milliseconds,
47 bool* success) {
48 // This POSIX version of this function only guarantees that we wait no less
49 // than |wait_milliseconds| for the process to exit. The child process may
50 // exit sometime before the timeout has ended but we may still block for up
51 // to 256 milliseconds after the fact.
53 // waitpid() has no direct support on POSIX for specifying a timeout, you can
54 // either ask it to block indefinitely or return immediately (WNOHANG).
55 // When a child process terminates a SIGCHLD signal is sent to the parent.
56 // Catching this signal would involve installing a signal handler which may
57 // affect other parts of the application and would be difficult to debug.
59 // Our strategy is to call waitpid() once up front to check if the process
60 // has already exited, otherwise to loop for wait_milliseconds, sleeping for
61 // at most 256 milliseconds each time using usleep() and then calling
62 // waitpid(). The amount of time we sleep starts out at 1 milliseconds, and
63 // we double it every 4 sleep cycles.
65 // usleep() is speced to exit if a signal is received for which a handler
66 // has been installed. This means that when a SIGCHLD is sent, it will exit
67 // depending on behavior external to this function.
69 // This function is used primarily for unit tests, if we want to use it in
70 // the application itself it would probably be best to examine other routes.
71 int status = -1;
72 pid_t ret_pid = HANDLE_EINTR(waitpid(handle, &status, WNOHANG));
73 static const int64 kMaxSleepInMicroseconds = 1 << 18; // ~256 milliseconds.
74 int64 max_sleep_time_usecs = 1 << 10; // ~1 milliseconds.
75 int64 double_sleep_time = 0;
77 // If the process hasn't exited yet, then sleep and try again.
78 Time wakeup_time = Time::Now() +
79 TimeDelta::FromMilliseconds(wait_milliseconds);
80 while (ret_pid == 0) {
81 Time now = Time::Now();
82 if (now > wakeup_time)
83 break;
84 // Guaranteed to be non-negative!
85 int64 sleep_time_usecs = (wakeup_time - now).InMicroseconds();
86 // Sleep for a bit while we wait for the process to finish.
87 if (sleep_time_usecs > max_sleep_time_usecs)
88 sleep_time_usecs = max_sleep_time_usecs;
90 // usleep() will return 0 and set errno to EINTR on receipt of a signal
91 // such as SIGCHLD.
92 usleep(sleep_time_usecs);
93 ret_pid = HANDLE_EINTR(waitpid(handle, &status, WNOHANG));
95 if ((max_sleep_time_usecs < kMaxSleepInMicroseconds) &&
96 (double_sleep_time++ % 4 == 0)) {
97 max_sleep_time_usecs *= 2;
101 if (success)
102 *success = (ret_pid != -1);
104 return status;
107 void StackDumpSignalHandler(int signal, siginfo_t* info, ucontext_t* context) {
108 LOG(ERROR) << "Received signal " << signal;
109 debug::StackTrace().PrintBacktrace();
111 // TODO(shess): Port to Linux.
112 #if defined(OS_MACOSX)
113 // TODO(shess): Port to 64-bit.
114 #if ARCH_CPU_32_BITS
115 char buf[1024];
116 size_t len;
118 // NOTE: Even |snprintf()| is not on the approved list for signal
119 // handlers, but buffered I/O is definitely not on the list due to
120 // potential for |malloc()|.
121 len = static_cast<size_t>(
122 snprintf(buf, sizeof(buf),
123 "ax: %x, bx: %x, cx: %x, dx: %x\n",
124 context->uc_mcontext->__ss.__eax,
125 context->uc_mcontext->__ss.__ebx,
126 context->uc_mcontext->__ss.__ecx,
127 context->uc_mcontext->__ss.__edx));
128 write(STDERR_FILENO, buf, std::min(len, sizeof(buf) - 1));
130 len = static_cast<size_t>(
131 snprintf(buf, sizeof(buf),
132 "di: %x, si: %x, bp: %x, sp: %x, ss: %x, flags: %x\n",
133 context->uc_mcontext->__ss.__edi,
134 context->uc_mcontext->__ss.__esi,
135 context->uc_mcontext->__ss.__ebp,
136 context->uc_mcontext->__ss.__esp,
137 context->uc_mcontext->__ss.__ss,
138 context->uc_mcontext->__ss.__eflags));
139 write(STDERR_FILENO, buf, std::min(len, sizeof(buf) - 1));
141 len = static_cast<size_t>(
142 snprintf(buf, sizeof(buf),
143 "ip: %x, cs: %x, ds: %x, es: %x, fs: %x, gs: %x\n",
144 context->uc_mcontext->__ss.__eip,
145 context->uc_mcontext->__ss.__cs,
146 context->uc_mcontext->__ss.__ds,
147 context->uc_mcontext->__ss.__es,
148 context->uc_mcontext->__ss.__fs,
149 context->uc_mcontext->__ss.__gs));
150 write(STDERR_FILENO, buf, std::min(len, sizeof(buf) - 1));
151 #endif // ARCH_CPU_32_BITS
152 #endif // defined(OS_MACOSX)
153 _exit(1);
156 void ResetChildSignalHandlersToDefaults() {
157 // The previous signal handlers are likely to be meaningless in the child's
158 // context so we reset them to the defaults for now. http://crbug.com/44953
159 // These signal handlers are set up at least in browser_main.cc:BrowserMain
160 // and process_util_posix.cc:EnableInProcessStackDumping.
161 signal(SIGHUP, SIG_DFL);
162 signal(SIGINT, SIG_DFL);
163 signal(SIGILL, SIG_DFL);
164 signal(SIGABRT, SIG_DFL);
165 signal(SIGFPE, SIG_DFL);
166 signal(SIGBUS, SIG_DFL);
167 signal(SIGSEGV, SIG_DFL);
168 signal(SIGSYS, SIG_DFL);
169 signal(SIGTERM, SIG_DFL);
172 } // anonymous namespace
174 ProcessId GetCurrentProcId() {
175 return getpid();
178 ProcessHandle GetCurrentProcessHandle() {
179 return GetCurrentProcId();
182 bool OpenProcessHandle(ProcessId pid, ProcessHandle* handle) {
183 // On Posix platforms, process handles are the same as PIDs, so we
184 // don't need to do anything.
185 *handle = pid;
186 return true;
189 bool OpenPrivilegedProcessHandle(ProcessId pid, ProcessHandle* handle) {
190 // On POSIX permissions are checked for each operation on process,
191 // not when opening a "handle".
192 return OpenProcessHandle(pid, handle);
195 bool OpenProcessHandleWithAccess(ProcessId pid,
196 uint32 access_flags,
197 ProcessHandle* handle) {
198 // On POSIX permissions are checked for each operation on process,
199 // not when opening a "handle".
200 return OpenProcessHandle(pid, handle);
203 void CloseProcessHandle(ProcessHandle process) {
204 // See OpenProcessHandle, nothing to do.
205 return;
208 ProcessId GetProcId(ProcessHandle process) {
209 return process;
212 // Attempts to kill the process identified by the given process
213 // entry structure. Ignores specified exit_code; posix can't force that.
214 // Returns true if this is successful, false otherwise.
215 bool KillProcess(ProcessHandle process_id, int exit_code, bool wait) {
216 DCHECK_GT(process_id, 1) << " tried to kill invalid process_id";
217 if (process_id <= 1)
218 return false;
219 static unsigned kMaxSleepMs = 1000;
220 unsigned sleep_ms = 4;
222 bool result = kill(process_id, SIGTERM) == 0;
224 if (result && wait) {
225 int tries = 60;
226 // The process may not end immediately due to pending I/O
227 bool exited = false;
228 while (tries-- > 0) {
229 pid_t pid = HANDLE_EINTR(waitpid(process_id, NULL, WNOHANG));
230 if (pid == process_id) {
231 exited = true;
232 break;
234 if (pid == -1) {
235 if (errno == ECHILD) {
236 // The wait may fail with ECHILD if another process also waited for
237 // the same pid, causing the process state to get cleaned up.
238 exited = true;
239 break;
241 DPLOG(ERROR) << "Error waiting for process " << process_id;
244 usleep(sleep_ms * 1000);
245 if (sleep_ms < kMaxSleepMs)
246 sleep_ms *= 2;
249 // If we're waiting and the child hasn't died by now, force it
250 // with a SIGKILL.
251 if (!exited)
252 result = kill(process_id, SIGKILL) == 0;
255 if (!result)
256 DPLOG(ERROR) << "Unable to terminate process " << process_id;
258 return result;
261 bool KillProcessGroup(ProcessHandle process_group_id) {
262 bool result = kill(-1 * process_group_id, SIGKILL) == 0;
263 if (!result)
264 PLOG(ERROR) << "Unable to terminate process group " << process_group_id;
265 return result;
268 // A class to handle auto-closing of DIR*'s.
269 class ScopedDIRClose {
270 public:
271 inline void operator()(DIR* x) const {
272 if (x) {
273 closedir(x);
277 typedef scoped_ptr_malloc<DIR, ScopedDIRClose> ScopedDIR;
279 #if defined(OS_LINUX)
280 static const rlim_t kSystemDefaultMaxFds = 8192;
281 static const char kFDDir[] = "/proc/self/fd";
282 #elif defined(OS_MACOSX)
283 static const rlim_t kSystemDefaultMaxFds = 256;
284 static const char kFDDir[] = "/dev/fd";
285 #elif defined(OS_SOLARIS)
286 static const rlim_t kSystemDefaultMaxFds = 8192;
287 static const char kFDDir[] = "/dev/fd";
288 #elif defined(OS_FREEBSD)
289 static const rlim_t kSystemDefaultMaxFds = 8192;
290 static const char kFDDir[] = "/dev/fd";
291 #elif defined(OS_OPENBSD)
292 static const rlim_t kSystemDefaultMaxFds = 256;
293 static const char kFDDir[] = "/dev/fd";
294 #endif
296 void CloseSuperfluousFds(const base::InjectiveMultimap& saved_mapping) {
297 // DANGER: no calls to malloc are allowed from now on:
298 // http://crbug.com/36678
300 // Get the maximum number of FDs possible.
301 struct rlimit nofile;
302 rlim_t max_fds;
303 if (getrlimit(RLIMIT_NOFILE, &nofile)) {
304 // getrlimit failed. Take a best guess.
305 max_fds = kSystemDefaultMaxFds;
306 RAW_LOG(ERROR, "getrlimit(RLIMIT_NOFILE) failed");
307 } else {
308 max_fds = nofile.rlim_cur;
311 if (max_fds > INT_MAX)
312 max_fds = INT_MAX;
314 DirReaderPosix fd_dir(kFDDir);
316 if (!fd_dir.IsValid()) {
317 // Fallback case: Try every possible fd.
318 for (rlim_t i = 0; i < max_fds; ++i) {
319 const int fd = static_cast<int>(i);
320 if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO)
321 continue;
322 InjectiveMultimap::const_iterator j;
323 for (j = saved_mapping.begin(); j != saved_mapping.end(); j++) {
324 if (fd == j->dest)
325 break;
327 if (j != saved_mapping.end())
328 continue;
330 // Since we're just trying to close anything we can find,
331 // ignore any error return values of close().
332 ignore_result(HANDLE_EINTR(close(fd)));
334 return;
337 const int dir_fd = fd_dir.fd();
339 for ( ; fd_dir.Next(); ) {
340 // Skip . and .. entries.
341 if (fd_dir.name()[0] == '.')
342 continue;
344 char *endptr;
345 errno = 0;
346 const long int fd = strtol(fd_dir.name(), &endptr, 10);
347 if (fd_dir.name()[0] == 0 || *endptr || fd < 0 || errno)
348 continue;
349 if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO)
350 continue;
351 InjectiveMultimap::const_iterator i;
352 for (i = saved_mapping.begin(); i != saved_mapping.end(); i++) {
353 if (fd == i->dest)
354 break;
356 if (i != saved_mapping.end())
357 continue;
358 if (fd == dir_fd)
359 continue;
361 // When running under Valgrind, Valgrind opens several FDs for its
362 // own use and will complain if we try to close them. All of
363 // these FDs are >= |max_fds|, so we can check against that here
364 // before closing. See https://bugs.kde.org/show_bug.cgi?id=191758
365 if (fd < static_cast<int>(max_fds)) {
366 int ret = HANDLE_EINTR(close(fd));
367 DPCHECK(ret == 0);
372 char** AlterEnvironment(const environment_vector& changes,
373 const char* const* const env) {
374 unsigned count = 0;
375 unsigned size = 0;
377 // First assume that all of the current environment will be included.
378 for (unsigned i = 0; env[i]; i++) {
379 const char *const pair = env[i];
380 count++;
381 size += strlen(pair) + 1 /* terminating NUL */;
384 for (environment_vector::const_iterator
385 j = changes.begin(); j != changes.end(); j++) {
386 bool found = false;
387 const char *pair;
389 for (unsigned i = 0; env[i]; i++) {
390 pair = env[i];
391 const char *const equals = strchr(pair, '=');
392 if (!equals)
393 continue;
394 const unsigned keylen = equals - pair;
395 if (keylen == j->first.size() &&
396 memcmp(pair, j->first.data(), keylen) == 0) {
397 found = true;
398 break;
402 // if found, we'll either be deleting or replacing this element.
403 if (found) {
404 count--;
405 size -= strlen(pair) + 1;
406 if (j->second.size())
407 found = false;
410 // if !found, then we have a new element to add.
411 if (!found && !j->second.empty()) {
412 count++;
413 size += j->first.size() + 1 /* '=' */ + j->second.size() + 1 /* NUL */;
417 count++; // for the final NULL
418 uint8_t *buffer = new uint8_t[sizeof(char*) * count + size];
419 char **const ret = reinterpret_cast<char**>(buffer);
420 unsigned k = 0;
421 char *scratch = reinterpret_cast<char*>(buffer + sizeof(char*) * count);
423 for (unsigned i = 0; env[i]; i++) {
424 const char *const pair = env[i];
425 const char *const equals = strchr(pair, '=');
426 if (!equals) {
427 const unsigned len = strlen(pair);
428 ret[k++] = scratch;
429 memcpy(scratch, pair, len + 1);
430 scratch += len + 1;
431 continue;
433 const unsigned keylen = equals - pair;
434 bool handled = false;
435 for (environment_vector::const_iterator
436 j = changes.begin(); j != changes.end(); j++) {
437 if (j->first.size() == keylen &&
438 memcmp(j->first.data(), pair, keylen) == 0) {
439 if (!j->second.empty()) {
440 ret[k++] = scratch;
441 memcpy(scratch, pair, keylen + 1);
442 scratch += keylen + 1;
443 memcpy(scratch, j->second.c_str(), j->second.size() + 1);
444 scratch += j->second.size() + 1;
446 handled = true;
447 break;
451 if (!handled) {
452 const unsigned len = strlen(pair);
453 ret[k++] = scratch;
454 memcpy(scratch, pair, len + 1);
455 scratch += len + 1;
459 // Now handle new elements
460 for (environment_vector::const_iterator
461 j = changes.begin(); j != changes.end(); j++) {
462 if (j->second.empty())
463 continue;
465 bool found = false;
466 for (unsigned i = 0; env[i]; i++) {
467 const char *const pair = env[i];
468 const char *const equals = strchr(pair, '=');
469 if (!equals)
470 continue;
471 const unsigned keylen = equals - pair;
472 if (keylen == j->first.size() &&
473 memcmp(pair, j->first.data(), keylen) == 0) {
474 found = true;
475 break;
479 if (!found) {
480 ret[k++] = scratch;
481 memcpy(scratch, j->first.data(), j->first.size());
482 scratch += j->first.size();
483 *scratch++ = '=';
484 memcpy(scratch, j->second.c_str(), j->second.size() + 1);
485 scratch += j->second.size() + 1;
489 ret[k] = NULL;
490 return ret;
493 bool LaunchAppImpl(
494 const std::vector<std::string>& argv,
495 const environment_vector& env_changes,
496 const file_handle_mapping_vector& fds_to_remap,
497 bool wait,
498 ProcessHandle* process_handle,
499 bool start_new_process_group) {
500 pid_t pid;
501 InjectiveMultimap fd_shuffle1, fd_shuffle2;
502 fd_shuffle1.reserve(fds_to_remap.size());
503 fd_shuffle2.reserve(fds_to_remap.size());
504 scoped_array<char*> argv_cstr(new char*[argv.size() + 1]);
505 scoped_array<char*> new_environ(AlterEnvironment(env_changes, environ));
507 pid = fork();
508 if (pid < 0) {
509 PLOG(ERROR) << "fork";
510 return false;
512 if (pid == 0) {
513 // Child process
515 // DANGER: fork() rule: in the child, if you don't end up doing exec*(),
516 // you call _exit() instead of exit(). This is because _exit() does not
517 // call any previously-registered (in the parent) exit handlers, which
518 // might do things like block waiting for threads that don't even exist
519 // in the child.
521 // If a child process uses the readline library, the process block forever.
522 // In BSD like OSes including OS X it is safe to assign /dev/null as stdin.
523 // See http://crbug.com/56596.
524 int null_fd = HANDLE_EINTR(open("/dev/null", O_RDONLY));
525 if (null_fd < 0) {
526 RAW_LOG(ERROR, "Failed to open /dev/null");
527 _exit(127);
530 file_util::ScopedFD null_fd_closer(&null_fd);
531 int new_fd = HANDLE_EINTR(dup2(null_fd, STDIN_FILENO));
532 if (new_fd != STDIN_FILENO) {
533 RAW_LOG(ERROR, "Failed to dup /dev/null for stdin");
534 _exit(127);
537 if (start_new_process_group) {
538 // Instead of inheriting the process group ID of the parent, the child
539 // starts off a new process group with pgid equal to its process ID.
540 if (setpgid(0, 0) < 0) {
541 RAW_LOG(ERROR, "setpgid failed");
542 _exit(127);
545 #if defined(OS_MACOSX)
546 RestoreDefaultExceptionHandler();
547 #endif
549 ResetChildSignalHandlersToDefaults();
551 #if 0
552 // When debugging it can be helpful to check that we really aren't making
553 // any hidden calls to malloc.
554 void *malloc_thunk =
555 reinterpret_cast<void*>(reinterpret_cast<intptr_t>(malloc) & ~4095);
556 mprotect(malloc_thunk, 4096, PROT_READ | PROT_WRITE | PROT_EXEC);
557 memset(reinterpret_cast<void*>(malloc), 0xff, 8);
558 #endif
560 // DANGER: no calls to malloc are allowed from now on:
561 // http://crbug.com/36678
563 for (file_handle_mapping_vector::const_iterator
564 it = fds_to_remap.begin(); it != fds_to_remap.end(); ++it) {
565 fd_shuffle1.push_back(InjectionArc(it->first, it->second, false));
566 fd_shuffle2.push_back(InjectionArc(it->first, it->second, false));
569 environ = new_environ.get();
571 // fd_shuffle1 is mutated by this call because it cannot malloc.
572 if (!ShuffleFileDescriptors(&fd_shuffle1))
573 _exit(127);
575 CloseSuperfluousFds(fd_shuffle2);
577 for (size_t i = 0; i < argv.size(); i++)
578 argv_cstr[i] = const_cast<char*>(argv[i].c_str());
579 argv_cstr[argv.size()] = NULL;
580 execvp(argv_cstr[0], argv_cstr.get());
581 RAW_LOG(ERROR, "LaunchApp: failed to execvp:");
582 RAW_LOG(ERROR, argv_cstr[0]);
583 _exit(127);
584 } else {
585 // Parent process
586 if (wait) {
587 // While this isn't strictly disk IO, waiting for another process to
588 // finish is the sort of thing ThreadRestrictions is trying to prevent.
589 base::ThreadRestrictions::AssertIOAllowed();
590 pid_t ret = HANDLE_EINTR(waitpid(pid, 0, 0));
591 DPCHECK(ret > 0);
594 if (process_handle)
595 *process_handle = pid;
598 return true;
601 bool LaunchApp(
602 const std::vector<std::string>& argv,
603 const environment_vector& env_changes,
604 const file_handle_mapping_vector& fds_to_remap,
605 bool wait,
606 ProcessHandle* process_handle) {
607 return LaunchAppImpl(argv, env_changes, fds_to_remap,
608 wait, process_handle, false);
611 bool LaunchAppInNewProcessGroup(
612 const std::vector<std::string>& argv,
613 const environment_vector& env_changes,
614 const file_handle_mapping_vector& fds_to_remap,
615 bool wait,
616 ProcessHandle* process_handle) {
617 return LaunchAppImpl(argv, env_changes, fds_to_remap, wait,
618 process_handle, true);
621 bool LaunchApp(const std::vector<std::string>& argv,
622 const file_handle_mapping_vector& fds_to_remap,
623 bool wait, ProcessHandle* process_handle) {
624 base::environment_vector no_env;
625 return LaunchApp(argv, no_env, fds_to_remap, wait, process_handle);
628 bool LaunchApp(const CommandLine& cl,
629 bool wait, bool start_hidden,
630 ProcessHandle* process_handle) {
631 file_handle_mapping_vector no_files;
632 return LaunchApp(cl.argv(), no_files, wait, process_handle);
635 ProcessMetrics::~ProcessMetrics() { }
637 void EnableTerminationOnHeapCorruption() {
638 // On POSIX, there nothing to do AFAIK.
641 bool EnableInProcessStackDumping() {
642 // When running in an application, our code typically expects SIGPIPE
643 // to be ignored. Therefore, when testing that same code, it should run
644 // with SIGPIPE ignored as well.
645 struct sigaction action;
646 action.sa_handler = SIG_IGN;
647 action.sa_flags = 0;
648 sigemptyset(&action.sa_mask);
649 bool success = (sigaction(SIGPIPE, &action, NULL) == 0);
651 sig_t handler = reinterpret_cast<sig_t>(&StackDumpSignalHandler);
652 success &= (signal(SIGILL, handler) != SIG_ERR);
653 success &= (signal(SIGABRT, handler) != SIG_ERR);
654 success &= (signal(SIGFPE, handler) != SIG_ERR);
655 success &= (signal(SIGBUS, handler) != SIG_ERR);
656 success &= (signal(SIGSEGV, handler) != SIG_ERR);
657 success &= (signal(SIGSYS, handler) != SIG_ERR);
659 return success;
662 void RaiseProcessToHighPriority() {
663 // On POSIX, we don't actually do anything here. We could try to nice() or
664 // setpriority() or sched_getscheduler, but these all require extra rights.
667 TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) {
668 int status = 0;
669 const pid_t result = HANDLE_EINTR(waitpid(handle, &status, WNOHANG));
670 if (result == -1) {
671 PLOG(ERROR) << "waitpid(" << handle << ")";
672 if (exit_code)
673 *exit_code = 0;
674 return TERMINATION_STATUS_NORMAL_TERMINATION;
675 } else if (result == 0) {
676 // the child hasn't exited yet.
677 if (exit_code)
678 *exit_code = 0;
679 return TERMINATION_STATUS_STILL_RUNNING;
682 if (exit_code)
683 *exit_code = status;
685 if (WIFSIGNALED(status)) {
686 switch (WTERMSIG(status)) {
687 case SIGABRT:
688 case SIGBUS:
689 case SIGFPE:
690 case SIGILL:
691 case SIGSEGV:
692 return TERMINATION_STATUS_PROCESS_CRASHED;
693 case SIGINT:
694 case SIGKILL:
695 case SIGTERM:
696 return TERMINATION_STATUS_PROCESS_WAS_KILLED;
697 default:
698 break;
702 if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
703 return TERMINATION_STATUS_ABNORMAL_TERMINATION;
705 return TERMINATION_STATUS_NORMAL_TERMINATION;
708 bool WaitForExitCode(ProcessHandle handle, int* exit_code) {
709 int status;
710 if (HANDLE_EINTR(waitpid(handle, &status, 0)) == -1) {
711 NOTREACHED();
712 return false;
715 if (WIFEXITED(status)) {
716 *exit_code = WEXITSTATUS(status);
717 return true;
720 // If it didn't exit cleanly, it must have been signaled.
721 DCHECK(WIFSIGNALED(status));
722 return false;
725 bool WaitForExitCodeWithTimeout(ProcessHandle handle, int* exit_code,
726 int64 timeout_milliseconds) {
727 bool waitpid_success = false;
728 int status = WaitpidWithTimeout(handle, timeout_milliseconds,
729 &waitpid_success);
730 if (status == -1)
731 return false;
732 if (!waitpid_success)
733 return false;
734 if (WIFSIGNALED(status)) {
735 *exit_code = -1;
736 return true;
738 if (WIFEXITED(status)) {
739 *exit_code = WEXITSTATUS(status);
740 return true;
742 return false;
745 #if defined(OS_MACOSX)
746 // Using kqueue on Mac so that we can wait on non-child processes.
747 // We can't use kqueues on child processes because we need to reap
748 // our own children using wait.
749 static bool WaitForSingleNonChildProcess(ProcessHandle handle,
750 int64 wait_milliseconds) {
751 int kq = kqueue();
752 if (kq == -1) {
753 PLOG(ERROR) << "kqueue";
754 return false;
757 struct kevent change = { 0 };
758 EV_SET(&change, handle, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL);
760 struct timespec spec;
761 struct timespec *spec_ptr;
762 if (wait_milliseconds != base::kNoTimeout) {
763 time_t sec = static_cast<time_t>(wait_milliseconds / 1000);
764 wait_milliseconds = wait_milliseconds - (sec * 1000);
765 spec.tv_sec = sec;
766 spec.tv_nsec = wait_milliseconds * 1000000L;
767 spec_ptr = &spec;
768 } else {
769 spec_ptr = NULL;
772 while(true) {
773 struct kevent event = { 0 };
774 int event_count = HANDLE_EINTR(kevent(kq, &change, 1, &event, 1, spec_ptr));
775 if (close(kq) != 0) {
776 PLOG(ERROR) << "close";
778 if (event_count < 0) {
779 PLOG(ERROR) << "kevent";
780 return false;
781 } else if (event_count == 0) {
782 if (wait_milliseconds != base::kNoTimeout) {
783 // Timed out.
784 return false;
786 } else if ((event_count == 1) &&
787 (handle == static_cast<pid_t>(event.ident)) &&
788 (event.filter == EVFILT_PROC)) {
789 if (event.fflags == NOTE_EXIT) {
790 return true;
791 } else if (event.flags == EV_ERROR) {
792 LOG(ERROR) << "kevent error " << event.data;
793 return false;
794 } else {
795 NOTREACHED();
796 return false;
798 } else {
799 NOTREACHED();
800 return false;
804 #endif // OS_MACOSX
806 bool WaitForSingleProcess(ProcessHandle handle, int64 wait_milliseconds) {
807 ProcessHandle parent_pid = GetParentProcessId(handle);
808 ProcessHandle our_pid = Process::Current().handle();
809 if (parent_pid != our_pid) {
810 #if defined(OS_MACOSX)
811 // On Mac we can wait on non child processes.
812 return WaitForSingleNonChildProcess(handle, wait_milliseconds);
813 #else
814 // Currently on Linux we can't handle non child processes.
815 NOTIMPLEMENTED();
816 #endif // OS_MACOSX
818 bool waitpid_success;
819 int status;
820 if (wait_milliseconds == base::kNoTimeout)
821 waitpid_success = (HANDLE_EINTR(waitpid(handle, &status, 0)) != -1);
822 else
823 status = WaitpidWithTimeout(handle, wait_milliseconds, &waitpid_success);
824 if (status != -1) {
825 DCHECK(waitpid_success);
826 return WIFEXITED(status);
827 } else {
828 return false;
832 int64 TimeValToMicroseconds(const struct timeval& tv) {
833 static const int kMicrosecondsPerSecond = 1000000;
834 int64 ret = tv.tv_sec; // Avoid (int * int) integer overflow.
835 ret *= kMicrosecondsPerSecond;
836 ret += tv.tv_usec;
837 return ret;
840 // Executes the application specified by |cl| and wait for it to exit. Stores
841 // the output (stdout) in |output|. If |do_search_path| is set, it searches the
842 // path for the application; in that case, |envp| must be null, and it will use
843 // the current environment. If |do_search_path| is false, |cl| should fully
844 // specify the path of the application, and |envp| will be used as the
845 // environment. Redirects stderr to /dev/null. Returns true on success
846 // (application launched and exited cleanly, with exit code indicating success).
847 static bool GetAppOutputInternal(const CommandLine& cl, char* const envp[],
848 std::string* output, size_t max_output,
849 bool do_search_path) {
850 // Doing a blocking wait for another command to finish counts as IO.
851 base::ThreadRestrictions::AssertIOAllowed();
853 int pipe_fd[2];
854 pid_t pid;
855 InjectiveMultimap fd_shuffle1, fd_shuffle2;
856 const std::vector<std::string>& argv = cl.argv();
857 scoped_array<char*> argv_cstr(new char*[argv.size() + 1]);
859 fd_shuffle1.reserve(3);
860 fd_shuffle2.reserve(3);
862 // Either |do_search_path| should be false or |envp| should be null, but not
863 // both.
864 DCHECK(!do_search_path ^ !envp);
866 if (pipe(pipe_fd) < 0)
867 return false;
869 switch (pid = fork()) {
870 case -1: // error
871 close(pipe_fd[0]);
872 close(pipe_fd[1]);
873 return false;
874 case 0: // child
876 #if defined(OS_MACOSX)
877 RestoreDefaultExceptionHandler();
878 #endif
879 // DANGER: no calls to malloc are allowed from now on:
880 // http://crbug.com/36678
882 // Obscure fork() rule: in the child, if you don't end up doing exec*(),
883 // you call _exit() instead of exit(). This is because _exit() does not
884 // call any previously-registered (in the parent) exit handlers, which
885 // might do things like block waiting for threads that don't even exist
886 // in the child.
887 int dev_null = open("/dev/null", O_WRONLY);
888 if (dev_null < 0)
889 _exit(127);
891 fd_shuffle1.push_back(InjectionArc(pipe_fd[1], STDOUT_FILENO, true));
892 fd_shuffle1.push_back(InjectionArc(dev_null, STDERR_FILENO, true));
893 fd_shuffle1.push_back(InjectionArc(dev_null, STDIN_FILENO, true));
894 // Adding another element here? Remeber to increase the argument to
895 // reserve(), above.
897 std::copy(fd_shuffle1.begin(), fd_shuffle1.end(),
898 std::back_inserter(fd_shuffle2));
900 if (!ShuffleFileDescriptors(&fd_shuffle1))
901 _exit(127);
903 CloseSuperfluousFds(fd_shuffle2);
905 for (size_t i = 0; i < argv.size(); i++)
906 argv_cstr[i] = const_cast<char*>(argv[i].c_str());
907 argv_cstr[argv.size()] = NULL;
908 if (do_search_path)
909 execvp(argv_cstr[0], argv_cstr.get());
910 else
911 execve(argv_cstr[0], argv_cstr.get(), envp);
912 _exit(127);
914 default: // parent
916 // Close our writing end of pipe now. Otherwise later read would not
917 // be able to detect end of child's output (in theory we could still
918 // write to the pipe).
919 close(pipe_fd[1]);
921 output->clear();
922 char buffer[256];
923 size_t output_buf_left = max_output;
924 ssize_t bytes_read = 1; // A lie to properly handle |max_output == 0|
925 // case in the logic below.
927 while (output_buf_left > 0) {
928 bytes_read = HANDLE_EINTR(read(pipe_fd[0], buffer,
929 std::min(output_buf_left, sizeof(buffer))));
930 if (bytes_read <= 0)
931 break;
932 output->append(buffer, bytes_read);
933 output_buf_left -= static_cast<size_t>(bytes_read);
935 close(pipe_fd[0]);
937 // Always wait for exit code (even if we know we'll declare success).
938 int exit_code = EXIT_FAILURE;
939 bool success = WaitForExitCode(pid, &exit_code);
941 // If we stopped because we read as much as we wanted, we always declare
942 // success (because the child may exit due to |SIGPIPE|).
943 if (output_buf_left || bytes_read <= 0) {
944 if (!success || exit_code != EXIT_SUCCESS)
945 return false;
948 return true;
953 bool GetAppOutput(const CommandLine& cl, std::string* output) {
954 // Run |execve()| with the current environment and store "unlimited" data.
955 return GetAppOutputInternal(cl, NULL, output,
956 std::numeric_limits<std::size_t>::max(), true);
959 // TODO(viettrungluu): Conceivably, we should have a timeout as well, so we
960 // don't hang if what we're calling hangs.
961 bool GetAppOutputRestricted(const CommandLine& cl,
962 std::string* output, size_t max_output) {
963 // Run |execve()| with the empty environment.
964 char* const empty_environ = NULL;
965 return GetAppOutputInternal(cl, &empty_environ, output, max_output, false);
968 bool WaitForProcessesToExit(const FilePath::StringType& executable_name,
969 int64 wait_milliseconds,
970 const ProcessFilter* filter) {
971 bool result = false;
973 // TODO(port): This is inefficient, but works if there are multiple procs.
974 // TODO(port): use waitpid to avoid leaving zombies around
976 base::Time end_time = base::Time::Now() +
977 base::TimeDelta::FromMilliseconds(wait_milliseconds);
978 do {
979 NamedProcessIterator iter(executable_name, filter);
980 if (!iter.NextProcessEntry()) {
981 result = true;
982 break;
984 base::PlatformThread::Sleep(100);
985 } while ((base::Time::Now() - end_time) > base::TimeDelta());
987 return result;
990 bool CleanupProcesses(const FilePath::StringType& executable_name,
991 int64 wait_milliseconds,
992 int exit_code,
993 const ProcessFilter* filter) {
994 bool exited_cleanly =
995 WaitForProcessesToExit(executable_name, wait_milliseconds,
996 filter);
997 if (!exited_cleanly)
998 KillProcesses(executable_name, exit_code, filter);
999 return exited_cleanly;
1002 } // namespace base