blob: 023f1e83c26650492a9eea052ae1a8d7d6551323 [file] [log] [blame]
[email protected]3b63f8f42011-03-28 01:54:151// Copyright (c) 2011 The Chromium Authors. All rights reserved.
[email protected]3d5617e2008-08-27 14:36:192// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]05d4b0a2009-01-29 17:51:515#include <dirent.h>
[email protected]c7856632009-01-13 17:38:496#include <errno.h>
[email protected]05d4b0a2009-01-29 17:51:517#include <fcntl.h>
[email protected]8cf7cebd2009-01-05 19:53:308#include <signal.h>
[email protected]05d4b0a2009-01-29 17:51:519#include <stdlib.h>
[email protected]0d83c732008-12-02 16:50:4710#include <sys/resource.h>
11#include <sys/time.h>
[email protected]3d5617e2008-08-27 14:36:1912#include <sys/types.h>
[email protected]43bc28322008-12-05 01:57:2113#include <sys/wait.h>
[email protected]3d5617e2008-08-27 14:36:1914#include <unistd.h>
[email protected]05d4b0a2009-01-29 17:51:5115
[email protected]fa3097a6a52008-12-17 22:41:5016#include <limits>
[email protected]3f04f2b2009-04-30 19:40:0317#include <set>
[email protected]3d5617e2008-08-27 14:36:1918
[email protected]5d91c9e2010-07-28 17:25:2819#include "base/command_line.h"
[email protected]cabe39c2010-02-02 02:28:1620#include "base/compiler_specific.h"
[email protected]72e243662011-06-11 00:46:1021#include "base/debug/debugger.h"
[email protected]58580352010-10-26 04:07:5022#include "base/debug/stack_trace.h"
[email protected]ef73044e2010-03-11 15:25:5423#include "base/dir_reader_posix.h"
[email protected]157c61b2009-05-01 21:37:3124#include "base/eintr_wrapper.h"
[email protected]955b7392011-03-09 00:49:2025#include "base/file_util.h"
[email protected]0d83c732008-12-02 16:50:4726#include "base/logging.h"
[email protected]3b63f8f42011-03-28 01:54:1527#include "base/memory/scoped_ptr.h"
[email protected]05d4b0a2009-01-29 17:51:5128#include "base/process_util.h"
[email protected]f1633932010-08-17 23:05:2829#include "base/stringprintf.h"
[email protected]44f9c952011-01-02 06:05:3930#include "base/synchronization/waitable_event.h"
[email protected]2f7a6ea2011-06-18 11:49:2731#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
[email protected]ce072a72010-12-31 20:02:1632#include "base/threading/platform_thread.h"
[email protected]34b99632011-01-01 01:01:0633#include "base/threading/thread_restrictions.h"
[email protected]43bc28322008-12-05 01:57:2134#include "base/time.h"
[email protected]3d5617e2008-08-27 14:36:1935
[email protected]c0028792010-01-12 00:39:1536#if defined(OS_MACOSX)
[email protected]ef73044e2010-03-11 15:25:5437#include <crt_externs.h>
[email protected]56f0f262011-02-24 17:14:3638#include <sys/event.h>
[email protected]ef73044e2010-03-11 15:25:5439#define environ (*_NSGetEnviron())
[email protected]ef73044e2010-03-11 15:25:5440#else
41extern char** environ;
[email protected]c0028792010-01-12 00:39:1542#endif
43
[email protected]aa660752008-11-14 03:39:4644namespace base {
[email protected]3d5617e2008-08-27 14:36:1945
[email protected]d6fc9fd2009-10-27 18:03:4746namespace {
47
[email protected]eaec38c2010-11-29 19:30:2348int WaitpidWithTimeout(ProcessHandle handle, int64 wait_milliseconds,
49 bool* success) {
[email protected]d6fc9fd2009-10-27 18:03:4750 // This POSIX version of this function only guarantees that we wait no less
[email protected]2d9bb0222010-04-02 08:24:0151 // than |wait_milliseconds| for the process to exit. The child process may
52 // exit sometime before the timeout has ended but we may still block for up
53 // to 256 milliseconds after the fact.
[email protected]d6fc9fd2009-10-27 18:03:4754 //
55 // waitpid() has no direct support on POSIX for specifying a timeout, you can
56 // either ask it to block indefinitely or return immediately (WNOHANG).
57 // When a child process terminates a SIGCHLD signal is sent to the parent.
58 // Catching this signal would involve installing a signal handler which may
59 // affect other parts of the application and would be difficult to debug.
60 //
61 // Our strategy is to call waitpid() once up front to check if the process
62 // has already exited, otherwise to loop for wait_milliseconds, sleeping for
[email protected]2d9bb0222010-04-02 08:24:0163 // at most 256 milliseconds each time using usleep() and then calling
64 // waitpid(). The amount of time we sleep starts out at 1 milliseconds, and
65 // we double it every 4 sleep cycles.
[email protected]d6fc9fd2009-10-27 18:03:4766 //
67 // usleep() is speced to exit if a signal is received for which a handler
68 // has been installed. This means that when a SIGCHLD is sent, it will exit
69 // depending on behavior external to this function.
70 //
[email protected]eaec38c2010-11-29 19:30:2371 // This function is used primarily for unit tests, if we want to use it in
72 // the application itself it would probably be best to examine other routes.
73 int status = -1;
74 pid_t ret_pid = HANDLE_EINTR(waitpid(handle, &status, WNOHANG));
[email protected]2d9bb0222010-04-02 08:24:0175 static const int64 kMaxSleepInMicroseconds = 1 << 18; // ~256 milliseconds.
76 int64 max_sleep_time_usecs = 1 << 10; // ~1 milliseconds.
[email protected]eaec38c2010-11-29 19:30:2377 int64 double_sleep_time = 0;
[email protected]d6fc9fd2009-10-27 18:03:4778
79 // If the process hasn't exited yet, then sleep and try again.
[email protected]2d9bb0222010-04-02 08:24:0180 Time wakeup_time = Time::Now() +
81 TimeDelta::FromMilliseconds(wait_milliseconds);
[email protected]d6fc9fd2009-10-27 18:03:4782 while (ret_pid == 0) {
83 Time now = Time::Now();
84 if (now > wakeup_time)
85 break;
86 // Guaranteed to be non-negative!
87 int64 sleep_time_usecs = (wakeup_time - now).InMicroseconds();
[email protected]2d9bb0222010-04-02 08:24:0188 // Sleep for a bit while we wait for the process to finish.
89 if (sleep_time_usecs > max_sleep_time_usecs)
90 sleep_time_usecs = max_sleep_time_usecs;
[email protected]d6fc9fd2009-10-27 18:03:4791
92 // usleep() will return 0 and set errno to EINTR on receipt of a signal
93 // such as SIGCHLD.
94 usleep(sleep_time_usecs);
[email protected]eaec38c2010-11-29 19:30:2395 ret_pid = HANDLE_EINTR(waitpid(handle, &status, WNOHANG));
[email protected]2d9bb0222010-04-02 08:24:0196
97 if ((max_sleep_time_usecs < kMaxSleepInMicroseconds) &&
98 (double_sleep_time++ % 4 == 0)) {
99 max_sleep_time_usecs *= 2;
100 }
[email protected]d6fc9fd2009-10-27 18:03:47101 }
102
[email protected]eaec38c2010-11-29 19:30:23103 if (success)
104 *success = (ret_pid != -1);
105
106 return status;
[email protected]d6fc9fd2009-10-27 18:03:47107}
108
[email protected]1e932112011-06-29 20:53:22109// Android has built-in crash handling.
110#if !defined(OS_ANDROID)
[email protected]7e3edc22010-11-22 22:31:00111void StackDumpSignalHandler(int signal, siginfo_t* info, ucontext_t* context) {
[email protected]72e243662011-06-11 00:46:10112 if (debug::BeingDebugged())
113 debug::BreakDebugger();
114
[email protected]7e868c962010-04-30 06:24:37115 LOG(ERROR) << "Received signal " << signal;
[email protected]58580352010-10-26 04:07:50116 debug::StackTrace().PrintBacktrace();
[email protected]7e3edc22010-11-22 22:31:00117
118 // TODO(shess): Port to Linux.
119#if defined(OS_MACOSX)
120 // TODO(shess): Port to 64-bit.
121#if ARCH_CPU_32_BITS
122 char buf[1024];
123 size_t len;
124
125 // NOTE: Even |snprintf()| is not on the approved list for signal
126 // handlers, but buffered I/O is definitely not on the list due to
127 // potential for |malloc()|.
128 len = static_cast<size_t>(
129 snprintf(buf, sizeof(buf),
130 "ax: %x, bx: %x, cx: %x, dx: %x\n",
131 context->uc_mcontext->__ss.__eax,
132 context->uc_mcontext->__ss.__ebx,
133 context->uc_mcontext->__ss.__ecx,
134 context->uc_mcontext->__ss.__edx));
135 write(STDERR_FILENO, buf, std::min(len, sizeof(buf) - 1));
136
137 len = static_cast<size_t>(
138 snprintf(buf, sizeof(buf),
139 "di: %x, si: %x, bp: %x, sp: %x, ss: %x, flags: %x\n",
140 context->uc_mcontext->__ss.__edi,
141 context->uc_mcontext->__ss.__esi,
142 context->uc_mcontext->__ss.__ebp,
143 context->uc_mcontext->__ss.__esp,
144 context->uc_mcontext->__ss.__ss,
145 context->uc_mcontext->__ss.__eflags));
146 write(STDERR_FILENO, buf, std::min(len, sizeof(buf) - 1));
147
148 len = static_cast<size_t>(
149 snprintf(buf, sizeof(buf),
150 "ip: %x, cs: %x, ds: %x, es: %x, fs: %x, gs: %x\n",
151 context->uc_mcontext->__ss.__eip,
152 context->uc_mcontext->__ss.__cs,
153 context->uc_mcontext->__ss.__ds,
154 context->uc_mcontext->__ss.__es,
155 context->uc_mcontext->__ss.__fs,
156 context->uc_mcontext->__ss.__gs));
157 write(STDERR_FILENO, buf, std::min(len, sizeof(buf) - 1));
158#endif // ARCH_CPU_32_BITS
159#endif // defined(OS_MACOSX)
[email protected]d6fc9fd2009-10-27 18:03:47160 _exit(1);
161}
[email protected]1e932112011-06-29 20:53:22162#endif // !defined(OS_ANDROID)
[email protected]d6fc9fd2009-10-27 18:03:47163
[email protected]620a0032010-09-04 02:32:59164void ResetChildSignalHandlersToDefaults() {
165 // The previous signal handlers are likely to be meaningless in the child's
166 // context so we reset them to the defaults for now. http://crbug.com/44953
[email protected]ff09a4f2011-04-08 13:42:04167 // These signal handlers are set up at least in browser_main.cc:BrowserMain
168 // and process_util_posix.cc:EnableInProcessStackDumping.
[email protected]620a0032010-09-04 02:32:59169 signal(SIGHUP, SIG_DFL);
170 signal(SIGINT, SIG_DFL);
[email protected]ff09a4f2011-04-08 13:42:04171 signal(SIGILL, SIG_DFL);
172 signal(SIGABRT, SIG_DFL);
173 signal(SIGFPE, SIG_DFL);
174 signal(SIGBUS, SIG_DFL);
175 signal(SIGSEGV, SIG_DFL);
176 signal(SIGSYS, SIG_DFL);
177 signal(SIGTERM, SIG_DFL);
[email protected]620a0032010-09-04 02:32:59178}
179
[email protected]fa289832010-03-19 20:30:30180} // anonymous namespace
[email protected]d6fc9fd2009-10-27 18:03:47181
[email protected]43cf3252009-04-01 09:19:37182ProcessId GetCurrentProcId() {
[email protected]3d5617e2008-08-27 14:36:19183 return getpid();
184}
185
[email protected]113ab132008-09-18 20:42:55186ProcessHandle GetCurrentProcessHandle() {
187 return GetCurrentProcId();
188}
189
[email protected]6c6cc802009-04-03 17:01:36190bool OpenProcessHandle(ProcessId pid, ProcessHandle* handle) {
[email protected]5986ed22009-02-06 00:19:17191 // On Posix platforms, process handles are the same as PIDs, so we
192 // don't need to do anything.
[email protected]6c6cc802009-04-03 17:01:36193 *handle = pid;
194 return true;
[email protected]5986ed22009-02-06 00:19:17195}
196
[email protected]5d438dbad2009-04-30 08:59:39197bool OpenPrivilegedProcessHandle(ProcessId pid, ProcessHandle* handle) {
198 // On POSIX permissions are checked for each operation on process,
199 // not when opening a "handle".
200 return OpenProcessHandle(pid, handle);
201}
202
[email protected]7d11f6d52010-10-12 21:44:23203bool OpenProcessHandleWithAccess(ProcessId pid,
204 uint32 access_flags,
205 ProcessHandle* handle) {
206 // On POSIX permissions are checked for each operation on process,
207 // not when opening a "handle".
208 return OpenProcessHandle(pid, handle);
209}
210
[email protected]5986ed22009-02-06 00:19:17211void CloseProcessHandle(ProcessHandle process) {
212 // See OpenProcessHandle, nothing to do.
213 return;
214}
215
[email protected]43cf3252009-04-01 09:19:37216ProcessId GetProcId(ProcessHandle process) {
[email protected]fadb8ea2008-08-27 15:36:37217 return process;
[email protected]3d5617e2008-08-27 14:36:19218}
[email protected]fadb8ea2008-08-27 15:36:37219
[email protected]8cf7cebd2009-01-05 19:53:30220// Attempts to kill the process identified by the given process
221// entry structure. Ignores specified exit_code; posix can't force that.
222// Returns true if this is successful, false otherwise.
[email protected]cd4fd152009-02-09 19:28:41223bool KillProcess(ProcessHandle process_id, int exit_code, bool wait) {
[email protected]9610ef242009-11-18 02:41:26224 DCHECK_GT(process_id, 1) << " tried to kill invalid process_id";
225 if (process_id <= 1)
[email protected]9fd697a2009-07-07 14:00:59226 return false;
[email protected]f2d2ec22010-08-13 15:13:04227 static unsigned kMaxSleepMs = 1000;
228 unsigned sleep_ms = 4;
[email protected]9fd697a2009-07-07 14:00:59229
[email protected]140a7cd2009-04-28 01:37:23230 bool result = kill(process_id, SIGTERM) == 0;
[email protected]8cf7cebd2009-01-05 19:53:30231
[email protected]140a7cd2009-04-28 01:37:23232 if (result && wait) {
[email protected]8cf7cebd2009-01-05 19:53:30233 int tries = 60;
[email protected]2f7a6ea2011-06-18 11:49:27234
235 if (RunningOnValgrind()) {
236 // Wait for some extra time when running under Valgrind since the child
237 // processes may take some time doing leak checking.
238 tries *= 2;
239 }
240
[email protected]8cf7cebd2009-01-05 19:53:30241 // The process may not end immediately due to pending I/O
[email protected]d24423742009-07-13 23:31:28242 bool exited = false;
[email protected]8cf7cebd2009-01-05 19:53:30243 while (tries-- > 0) {
[email protected]a4dc33f2009-10-20 15:09:55244 pid_t pid = HANDLE_EINTR(waitpid(process_id, NULL, WNOHANG));
[email protected]d24423742009-07-13 23:31:28245 if (pid == process_id) {
246 exited = true;
[email protected]8cf7cebd2009-01-05 19:53:30247 break;
[email protected]d24423742009-07-13 23:31:28248 }
[email protected]bf4878d2010-06-16 20:12:01249 if (pid == -1) {
250 if (errno == ECHILD) {
251 // The wait may fail with ECHILD if another process also waited for
252 // the same pid, causing the process state to get cleaned up.
253 exited = true;
254 break;
255 }
256 DPLOG(ERROR) << "Error waiting for process " << process_id;
257 }
[email protected]140a7cd2009-04-28 01:37:23258
[email protected]f2d2ec22010-08-13 15:13:04259 usleep(sleep_ms * 1000);
260 if (sleep_ms < kMaxSleepMs)
261 sleep_ms *= 2;
[email protected]8cf7cebd2009-01-05 19:53:30262 }
[email protected]140a7cd2009-04-28 01:37:23263
[email protected]443b80e2010-12-14 00:42:23264 // If we're waiting and the child hasn't died by now, force it
265 // with a SIGKILL.
[email protected]32cd5302009-11-20 19:30:59266 if (!exited)
[email protected]d24423742009-07-13 23:31:28267 result = kill(process_id, SIGKILL) == 0;
[email protected]8cf7cebd2009-01-05 19:53:30268 }
[email protected]140a7cd2009-04-28 01:37:23269
[email protected]32cd5302009-11-20 19:30:59270 if (!result)
271 DPLOG(ERROR) << "Unable to terminate process " << process_id;
[email protected]140a7cd2009-04-28 01:37:23272
[email protected]8cf7cebd2009-01-05 19:53:30273 return result;
274}
275
[email protected]61b93f88f2010-09-22 17:28:30276bool KillProcessGroup(ProcessHandle process_group_id) {
277 bool result = kill(-1 * process_group_id, SIGKILL) == 0;
278 if (!result)
279 PLOG(ERROR) << "Unable to terminate process group " << process_group_id;
280 return result;
281}
282
[email protected]05d4b0a2009-01-29 17:51:51283// A class to handle auto-closing of DIR*'s.
284class ScopedDIRClose {
285 public:
286 inline void operator()(DIR* x) const {
287 if (x) {
288 closedir(x);
289 }
290 }
291};
292typedef scoped_ptr_malloc<DIR, ScopedDIRClose> ScopedDIR;
293
[email protected]aec92f832009-05-06 16:40:12294#if defined(OS_LINUX)
295 static const rlim_t kSystemDefaultMaxFds = 8192;
[email protected]ef73044e2010-03-11 15:25:54296 static const char kFDDir[] = "/proc/self/fd";
[email protected]aec92f832009-05-06 16:40:12297#elif defined(OS_MACOSX)
298 static const rlim_t kSystemDefaultMaxFds = 256;
[email protected]ef73044e2010-03-11 15:25:54299 static const char kFDDir[] = "/dev/fd";
[email protected]a1208912010-02-17 14:15:08300#elif defined(OS_SOLARIS)
301 static const rlim_t kSystemDefaultMaxFds = 8192;
[email protected]ef73044e2010-03-11 15:25:54302 static const char kFDDir[] = "/dev/fd";
[email protected]4a34ce02009-08-31 22:25:00303#elif defined(OS_FREEBSD)
304 static const rlim_t kSystemDefaultMaxFds = 8192;
[email protected]ef73044e2010-03-11 15:25:54305 static const char kFDDir[] = "/dev/fd";
[email protected]8d578822010-01-25 23:54:54306#elif defined(OS_OPENBSD)
307 static const rlim_t kSystemDefaultMaxFds = 256;
[email protected]ef73044e2010-03-11 15:25:54308 static const char kFDDir[] = "/dev/fd";
[email protected]1e932112011-06-29 20:53:22309#elif defined(OS_ANDROID)
310 static const rlim_t kSystemDefaultMaxFds = 1024;
311 static const char kFDDir[] = "/proc/self/fd";
[email protected]aec92f832009-05-06 16:40:12312#endif
[email protected]ef73044e2010-03-11 15:25:54313
314void CloseSuperfluousFds(const base::InjectiveMultimap& saved_mapping) {
315 // DANGER: no calls to malloc are allowed from now on:
316 // http://crbug.com/36678
[email protected]3f04f2b2009-04-30 19:40:03317
[email protected]aec92f832009-05-06 16:40:12318 // Get the maximum number of FDs possible.
319 struct rlimit nofile;
320 rlim_t max_fds;
321 if (getrlimit(RLIMIT_NOFILE, &nofile)) {
322 // getrlimit failed. Take a best guess.
323 max_fds = kSystemDefaultMaxFds;
[email protected]ff09a4f2011-04-08 13:42:04324 RAW_LOG(ERROR, "getrlimit(RLIMIT_NOFILE) failed");
[email protected]aec92f832009-05-06 16:40:12325 } else {
326 max_fds = nofile.rlim_cur;
327 }
328
329 if (max_fds > INT_MAX)
330 max_fds = INT_MAX;
331
[email protected]ef73044e2010-03-11 15:25:54332 DirReaderPosix fd_dir(kFDDir);
[email protected]3f04f2b2009-04-30 19:40:03333
[email protected]ef73044e2010-03-11 15:25:54334 if (!fd_dir.IsValid()) {
[email protected]aec92f832009-05-06 16:40:12335 // Fallback case: Try every possible fd.
336 for (rlim_t i = 0; i < max_fds; ++i) {
[email protected]3f04f2b2009-04-30 19:40:03337 const int fd = static_cast<int>(i);
[email protected]ef73044e2010-03-11 15:25:54338 if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO)
339 continue;
[email protected]40350b12010-03-30 17:29:27340 InjectiveMultimap::const_iterator j;
341 for (j = saved_mapping.begin(); j != saved_mapping.end(); j++) {
342 if (fd == j->dest)
[email protected]ef73044e2010-03-11 15:25:54343 break;
344 }
[email protected]40350b12010-03-30 17:29:27345 if (j != saved_mapping.end())
[email protected]3f04f2b2009-04-30 19:40:03346 continue;
347
[email protected]cabe39c2010-02-02 02:28:16348 // Since we're just trying to close anything we can find,
349 // ignore any error return values of close().
[email protected]ff09a4f2011-04-08 13:42:04350 ignore_result(HANDLE_EINTR(close(fd)));
[email protected]3f04f2b2009-04-30 19:40:03351 }
352 return;
353 }
354
[email protected]ef73044e2010-03-11 15:25:54355 const int dir_fd = fd_dir.fd();
356
357 for ( ; fd_dir.Next(); ) {
[email protected]3f04f2b2009-04-30 19:40:03358 // Skip . and .. entries.
[email protected]ef73044e2010-03-11 15:25:54359 if (fd_dir.name()[0] == '.')
[email protected]3f04f2b2009-04-30 19:40:03360 continue;
361
362 char *endptr;
363 errno = 0;
[email protected]ef73044e2010-03-11 15:25:54364 const long int fd = strtol(fd_dir.name(), &endptr, 10);
365 if (fd_dir.name()[0] == 0 || *endptr || fd < 0 || errno)
[email protected]3f04f2b2009-04-30 19:40:03366 continue;
[email protected]ef73044e2010-03-11 15:25:54367 if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO)
368 continue;
369 InjectiveMultimap::const_iterator i;
370 for (i = saved_mapping.begin(); i != saved_mapping.end(); i++) {
371 if (fd == i->dest)
372 break;
373 }
374 if (i != saved_mapping.end())
[email protected]3f04f2b2009-04-30 19:40:03375 continue;
[email protected]699de0b2009-06-07 23:03:08376 if (fd == dir_fd)
377 continue;
[email protected]3f04f2b2009-04-30 19:40:03378
[email protected]aec92f832009-05-06 16:40:12379 // When running under Valgrind, Valgrind opens several FDs for its
380 // own use and will complain if we try to close them. All of
381 // these FDs are >= |max_fds|, so we can check against that here
382 // before closing. See https://bugs.kde.org/show_bug.cgi?id=191758
[email protected]cabe39c2010-02-02 02:28:16383 if (fd < static_cast<int>(max_fds)) {
384 int ret = HANDLE_EINTR(close(fd));
385 DPCHECK(ret == 0);
386 }
[email protected]3f04f2b2009-04-30 19:40:03387 }
388}
389
[email protected]ef73044e2010-03-11 15:25:54390char** AlterEnvironment(const environment_vector& changes,
391 const char* const* const env) {
392 unsigned count = 0;
393 unsigned size = 0;
394
395 // First assume that all of the current environment will be included.
396 for (unsigned i = 0; env[i]; i++) {
397 const char *const pair = env[i];
398 count++;
399 size += strlen(pair) + 1 /* terminating NUL */;
400 }
401
402 for (environment_vector::const_iterator
403 j = changes.begin(); j != changes.end(); j++) {
404 bool found = false;
405 const char *pair;
406
407 for (unsigned i = 0; env[i]; i++) {
408 pair = env[i];
409 const char *const equals = strchr(pair, '=');
410 if (!equals)
411 continue;
412 const unsigned keylen = equals - pair;
413 if (keylen == j->first.size() &&
414 memcmp(pair, j->first.data(), keylen) == 0) {
415 found = true;
416 break;
417 }
418 }
419
420 // if found, we'll either be deleting or replacing this element.
421 if (found) {
422 count--;
423 size -= strlen(pair) + 1;
424 if (j->second.size())
425 found = false;
426 }
427
428 // if !found, then we have a new element to add.
[email protected]6775e40a2011-03-04 21:03:47429 if (!found && !j->second.empty()) {
[email protected]ef73044e2010-03-11 15:25:54430 count++;
431 size += j->first.size() + 1 /* '=' */ + j->second.size() + 1 /* NUL */;
432 }
433 }
434
435 count++; // for the final NULL
436 uint8_t *buffer = new uint8_t[sizeof(char*) * count + size];
437 char **const ret = reinterpret_cast<char**>(buffer);
438 unsigned k = 0;
439 char *scratch = reinterpret_cast<char*>(buffer + sizeof(char*) * count);
440
441 for (unsigned i = 0; env[i]; i++) {
442 const char *const pair = env[i];
443 const char *const equals = strchr(pair, '=');
444 if (!equals) {
445 const unsigned len = strlen(pair);
446 ret[k++] = scratch;
447 memcpy(scratch, pair, len + 1);
448 scratch += len + 1;
449 continue;
450 }
451 const unsigned keylen = equals - pair;
452 bool handled = false;
453 for (environment_vector::const_iterator
454 j = changes.begin(); j != changes.end(); j++) {
455 if (j->first.size() == keylen &&
456 memcmp(j->first.data(), pair, keylen) == 0) {
457 if (!j->second.empty()) {
458 ret[k++] = scratch;
459 memcpy(scratch, pair, keylen + 1);
460 scratch += keylen + 1;
461 memcpy(scratch, j->second.c_str(), j->second.size() + 1);
462 scratch += j->second.size() + 1;
463 }
464 handled = true;
465 break;
466 }
467 }
468
469 if (!handled) {
470 const unsigned len = strlen(pair);
471 ret[k++] = scratch;
472 memcpy(scratch, pair, len + 1);
473 scratch += len + 1;
474 }
475 }
476
477 // Now handle new elements
478 for (environment_vector::const_iterator
479 j = changes.begin(); j != changes.end(); j++) {
[email protected]f6b8ce32011-03-02 00:03:18480 if (j->second.empty())
[email protected]ef73044e2010-03-11 15:25:54481 continue;
482
483 bool found = false;
484 for (unsigned i = 0; env[i]; i++) {
485 const char *const pair = env[i];
486 const char *const equals = strchr(pair, '=');
487 if (!equals)
488 continue;
489 const unsigned keylen = equals - pair;
490 if (keylen == j->first.size() &&
491 memcmp(pair, j->first.data(), keylen) == 0) {
492 found = true;
493 break;
494 }
495 }
496
497 if (!found) {
498 ret[k++] = scratch;
499 memcpy(scratch, j->first.data(), j->first.size());
500 scratch += j->first.size();
501 *scratch++ = '=';
502 memcpy(scratch, j->second.c_str(), j->second.size() + 1);
503 scratch += j->second.size() + 1;
504 }
505 }
506
507 ret[k] = NULL;
508 return ret;
509}
510
[email protected]61b93f88f2010-09-22 17:28:30511bool LaunchAppImpl(
[email protected]c0028792010-01-12 00:39:15512 const std::vector<std::string>& argv,
[email protected]ef73044e2010-03-11 15:25:54513 const environment_vector& env_changes,
[email protected]c0028792010-01-12 00:39:15514 const file_handle_mapping_vector& fds_to_remap,
515 bool wait,
[email protected]61b93f88f2010-09-22 17:28:30516 ProcessHandle* process_handle,
[email protected]2b64f7b2011-06-28 19:06:46517 bool start_new_process_group) {
518 pid_t pid;
[email protected]ef73044e2010-03-11 15:25:54519 InjectiveMultimap fd_shuffle1, fd_shuffle2;
520 fd_shuffle1.reserve(fds_to_remap.size());
521 fd_shuffle2.reserve(fds_to_remap.size());
522 scoped_array<char*> argv_cstr(new char*[argv.size() + 1]);
523 scoped_array<char*> new_environ(AlterEnvironment(env_changes, environ));
524
[email protected]2b64f7b2011-06-28 19:06:46525 pid = fork();
[email protected]56f0f262011-02-24 17:14:36526 if (pid < 0) {
527 PLOG(ERROR) << "fork";
[email protected]2aea9e092009-08-06 20:03:01528 return false;
[email protected]56f0f262011-02-24 17:14:36529 }
[email protected]2aea9e092009-08-06 20:03:01530 if (pid == 0) {
531 // Child process
[email protected]61b93f88f2010-09-22 17:28:30532
[email protected]ff09a4f2011-04-08 13:42:04533 // DANGER: fork() rule: in the child, if you don't end up doing exec*(),
534 // you call _exit() instead of exit(). This is because _exit() does not
535 // call any previously-registered (in the parent) exit handlers, which
536 // might do things like block waiting for threads that don't even exist
537 // in the child.
538
[email protected]955b7392011-03-09 00:49:20539 // If a child process uses the readline library, the process block forever.
540 // In BSD like OSes including OS X it is safe to assign /dev/null as stdin.
541 // See http://crbug.com/56596.
542 int null_fd = HANDLE_EINTR(open("/dev/null", O_RDONLY));
543 if (null_fd < 0) {
[email protected]ff09a4f2011-04-08 13:42:04544 RAW_LOG(ERROR, "Failed to open /dev/null");
545 _exit(127);
546 }
547
548 file_util::ScopedFD null_fd_closer(&null_fd);
549 int new_fd = HANDLE_EINTR(dup2(null_fd, STDIN_FILENO));
550 if (new_fd != STDIN_FILENO) {
551 RAW_LOG(ERROR, "Failed to dup /dev/null for stdin");
552 _exit(127);
[email protected]955b7392011-03-09 00:49:20553 }
554
[email protected]61b93f88f2010-09-22 17:28:30555 if (start_new_process_group) {
556 // Instead of inheriting the process group ID of the parent, the child
557 // starts off a new process group with pgid equal to its process ID.
[email protected]56f0f262011-02-24 17:14:36558 if (setpgid(0, 0) < 0) {
[email protected]ff09a4f2011-04-08 13:42:04559 RAW_LOG(ERROR, "setpgid failed");
560 _exit(127);
[email protected]56f0f262011-02-24 17:14:36561 }
[email protected]61b93f88f2010-09-22 17:28:30562 }
[email protected]e9a8c19f2009-09-03 21:27:36563#if defined(OS_MACOSX)
564 RestoreDefaultExceptionHandler();
565#endif
566
[email protected]620a0032010-09-04 02:32:59567 ResetChildSignalHandlersToDefaults();
[email protected]01aa3cd2010-06-02 18:47:55568
[email protected]ef73044e2010-03-11 15:25:54569#if 0
570 // When debugging it can be helpful to check that we really aren't making
571 // any hidden calls to malloc.
572 void *malloc_thunk =
573 reinterpret_cast<void*>(reinterpret_cast<intptr_t>(malloc) & ~4095);
574 mprotect(malloc_thunk, 4096, PROT_READ | PROT_WRITE | PROT_EXEC);
575 memset(reinterpret_cast<void*>(malloc), 0xff, 8);
576#endif
577
578 // DANGER: no calls to malloc are allowed from now on:
579 // http://crbug.com/36678
580
[email protected]e6572302009-08-21 17:05:54581 for (file_handle_mapping_vector::const_iterator
582 it = fds_to_remap.begin(); it != fds_to_remap.end(); ++it) {
[email protected]ef73044e2010-03-11 15:25:54583 fd_shuffle1.push_back(InjectionArc(it->first, it->second, false));
584 fd_shuffle2.push_back(InjectionArc(it->first, it->second, false));
[email protected]e6572302009-08-21 17:05:54585 }
[email protected]2aea9e092009-08-06 20:03:01586
[email protected]ef73044e2010-03-11 15:25:54587 environ = new_environ.get();
[email protected]2aea9e092009-08-06 20:03:01588
[email protected]ef73044e2010-03-11 15:25:54589 // fd_shuffle1 is mutated by this call because it cannot malloc.
590 if (!ShuffleFileDescriptors(&fd_shuffle1))
[email protected]2aea9e092009-08-06 20:03:01591 _exit(127);
592
[email protected]ef73044e2010-03-11 15:25:54593 CloseSuperfluousFds(fd_shuffle2);
[email protected]e6572302009-08-21 17:05:54594
[email protected]e6572302009-08-21 17:05:54595 for (size_t i = 0; i < argv.size(); i++)
596 argv_cstr[i] = const_cast<char*>(argv[i].c_str());
597 argv_cstr[argv.size()] = NULL;
[email protected]2aea9e092009-08-06 20:03:01598 execvp(argv_cstr[0], argv_cstr.get());
[email protected]ef73044e2010-03-11 15:25:54599 RAW_LOG(ERROR, "LaunchApp: failed to execvp:");
600 RAW_LOG(ERROR, argv_cstr[0]);
[email protected]2aea9e092009-08-06 20:03:01601 _exit(127);
602 } else {
603 // Parent process
[email protected]cabe39c2010-02-02 02:28:16604 if (wait) {
[email protected]b42c4652010-12-04 03:23:53605 // While this isn't strictly disk IO, waiting for another process to
606 // finish is the sort of thing ThreadRestrictions is trying to prevent.
607 base::ThreadRestrictions::AssertIOAllowed();
[email protected]cabe39c2010-02-02 02:28:16608 pid_t ret = HANDLE_EINTR(waitpid(pid, 0, 0));
609 DPCHECK(ret > 0);
610 }
[email protected]2aea9e092009-08-06 20:03:01611
612 if (process_handle)
613 *process_handle = pid;
614 }
615
616 return true;
617}
618
[email protected]61b93f88f2010-09-22 17:28:30619bool LaunchApp(
620 const std::vector<std::string>& argv,
621 const environment_vector& env_changes,
622 const file_handle_mapping_vector& fds_to_remap,
623 bool wait,
624 ProcessHandle* process_handle) {
625 return LaunchAppImpl(argv, env_changes, fds_to_remap,
[email protected]2b64f7b2011-06-28 19:06:46626 wait, process_handle, false);
[email protected]61b93f88f2010-09-22 17:28:30627}
628
629bool LaunchAppInNewProcessGroup(
630 const std::vector<std::string>& argv,
631 const environment_vector& env_changes,
632 const file_handle_mapping_vector& fds_to_remap,
633 bool wait,
634 ProcessHandle* process_handle) {
635 return LaunchAppImpl(argv, env_changes, fds_to_remap, wait,
[email protected]2b64f7b2011-06-28 19:06:46636 process_handle, true);
[email protected]61b93f88f2010-09-22 17:28:30637}
638
[email protected]2aea9e092009-08-06 20:03:01639bool LaunchApp(const std::vector<std::string>& argv,
640 const file_handle_mapping_vector& fds_to_remap,
641 bool wait, ProcessHandle* process_handle) {
642 base::environment_vector no_env;
643 return LaunchApp(argv, no_env, fds_to_remap, wait, process_handle);
644}
645
646bool LaunchApp(const CommandLine& cl,
647 bool wait, bool start_hidden,
648 ProcessHandle* process_handle) {
649 file_handle_mapping_vector no_files;
650 return LaunchApp(cl.argv(), no_files, wait, process_handle);
651}
652
[email protected]0b100bc8b2008-10-14 20:49:16653ProcessMetrics::~ProcessMetrics() { }
654
[email protected]c9d40872008-09-24 12:58:37655void EnableTerminationOnHeapCorruption() {
656 // On POSIX, there nothing to do AFAIK.
657}
658
[email protected]d6fc9fd2009-10-27 18:03:47659bool EnableInProcessStackDumping() {
660 // When running in an application, our code typically expects SIGPIPE
661 // to be ignored. Therefore, when testing that same code, it should run
662 // with SIGPIPE ignored as well.
663 struct sigaction action;
664 action.sa_handler = SIG_IGN;
665 action.sa_flags = 0;
666 sigemptyset(&action.sa_mask);
667 bool success = (sigaction(SIGPIPE, &action, NULL) == 0);
668
[email protected]1e932112011-06-29 20:53:22669 // Android has built-in crash handling, so no need to hook the signals.
670#if !defined(OS_ANDROID)
[email protected]7e3edc22010-11-22 22:31:00671 sig_t handler = reinterpret_cast<sig_t>(&StackDumpSignalHandler);
672 success &= (signal(SIGILL, handler) != SIG_ERR);
673 success &= (signal(SIGABRT, handler) != SIG_ERR);
674 success &= (signal(SIGFPE, handler) != SIG_ERR);
675 success &= (signal(SIGBUS, handler) != SIG_ERR);
676 success &= (signal(SIGSEGV, handler) != SIG_ERR);
677 success &= (signal(SIGSYS, handler) != SIG_ERR);
[email protected]1e932112011-06-29 20:53:22678#endif
[email protected]7e868c962010-04-30 06:24:37679
[email protected]d6fc9fd2009-10-27 18:03:47680 return success;
681}
682
[email protected]3d5617e2008-08-27 14:36:19683void RaiseProcessToHighPriority() {
684 // On POSIX, we don't actually do anything here. We could try to nice() or
685 // setpriority() or sched_getscheduler, but these all require extra rights.
686}
687
[email protected]443b80e2010-12-14 00:42:23688TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) {
689 int status = 0;
[email protected]eaec38c2010-11-29 19:30:23690 const pid_t result = HANDLE_EINTR(waitpid(handle, &status, WNOHANG));
691 if (result == -1) {
692 PLOG(ERROR) << "waitpid(" << handle << ")";
[email protected]443b80e2010-12-14 00:42:23693 if (exit_code)
694 *exit_code = 0;
695 return TERMINATION_STATUS_NORMAL_TERMINATION;
[email protected]eaec38c2010-11-29 19:30:23696 } else if (result == 0) {
697 // the child hasn't exited yet.
[email protected]443b80e2010-12-14 00:42:23698 if (exit_code)
699 *exit_code = 0;
700 return TERMINATION_STATUS_STILL_RUNNING;
[email protected]9c19aa12009-01-21 13:50:11701 }
702
[email protected]443b80e2010-12-14 00:42:23703 if (exit_code)
704 *exit_code = status;
[email protected]140a7cd2009-04-28 01:37:23705
[email protected]9c19aa12009-01-21 13:50:11706 if (WIFSIGNALED(status)) {
[email protected]2fdc86a2010-01-26 23:08:02707 switch (WTERMSIG(status)) {
[email protected]22b61ba2010-10-19 18:25:47708 case SIGABRT:
[email protected]443b80e2010-12-14 00:42:23709 case SIGBUS:
[email protected]22b61ba2010-10-19 18:25:47710 case SIGFPE:
[email protected]443b80e2010-12-14 00:42:23711 case SIGILL:
712 case SIGSEGV:
713 return TERMINATION_STATUS_PROCESS_CRASHED;
714 case SIGINT:
715 case SIGKILL:
716 case SIGTERM:
717 return TERMINATION_STATUS_PROCESS_WAS_KILLED;
[email protected]9c19aa12009-01-21 13:50:11718 default:
[email protected]443b80e2010-12-14 00:42:23719 break;
[email protected]9c19aa12009-01-21 13:50:11720 }
721 }
722
[email protected]443b80e2010-12-14 00:42:23723 if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
724 return TERMINATION_STATUS_ABNORMAL_TERMINATION;
[email protected]9c19aa12009-01-21 13:50:11725
[email protected]443b80e2010-12-14 00:42:23726 return TERMINATION_STATUS_NORMAL_TERMINATION;
[email protected]9c19aa12009-01-21 13:50:11727}
728
[email protected]c7856632009-01-13 17:38:49729bool WaitForExitCode(ProcessHandle handle, int* exit_code) {
730 int status;
[email protected]157c61b2009-05-01 21:37:31731 if (HANDLE_EINTR(waitpid(handle, &status, 0)) == -1) {
732 NOTREACHED();
733 return false;
[email protected]c7856632009-01-13 17:38:49734 }
735
736 if (WIFEXITED(status)) {
737 *exit_code = WEXITSTATUS(status);
738 return true;
739 }
740
741 // If it didn't exit cleanly, it must have been signaled.
742 DCHECK(WIFSIGNALED(status));
743 return false;
744}
745
[email protected]8004e682010-03-16 07:41:22746bool WaitForExitCodeWithTimeout(ProcessHandle handle, int* exit_code,
747 int64 timeout_milliseconds) {
[email protected]eaec38c2010-11-29 19:30:23748 bool waitpid_success = false;
749 int status = WaitpidWithTimeout(handle, timeout_milliseconds,
750 &waitpid_success);
751 if (status == -1)
752 return false;
753 if (!waitpid_success)
[email protected]8004e682010-03-16 07:41:22754 return false;
[email protected]8004e682010-03-16 07:41:22755 if (WIFSIGNALED(status)) {
756 *exit_code = -1;
757 return true;
758 }
[email protected]40bbe592011-04-06 12:18:20759 if (WIFEXITED(status)) {
760 *exit_code = WEXITSTATUS(status);
761 return true;
762 }
763 return false;
[email protected]8004e682010-03-16 07:41:22764}
765
[email protected]56f0f262011-02-24 17:14:36766#if defined(OS_MACOSX)
767// Using kqueue on Mac so that we can wait on non-child processes.
768// We can't use kqueues on child processes because we need to reap
769// our own children using wait.
770static bool WaitForSingleNonChildProcess(ProcessHandle handle,
771 int64 wait_milliseconds) {
772 int kq = kqueue();
773 if (kq == -1) {
774 PLOG(ERROR) << "kqueue";
775 return false;
776 }
777
778 struct kevent change = { 0 };
779 EV_SET(&change, handle, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL);
780
781 struct timespec spec;
782 struct timespec *spec_ptr;
783 if (wait_milliseconds != base::kNoTimeout) {
784 time_t sec = static_cast<time_t>(wait_milliseconds / 1000);
785 wait_milliseconds = wait_milliseconds - (sec * 1000);
786 spec.tv_sec = sec;
787 spec.tv_nsec = wait_milliseconds * 1000000L;
788 spec_ptr = &spec;
789 } else {
790 spec_ptr = NULL;
791 }
792
793 while(true) {
794 struct kevent event = { 0 };
795 int event_count = HANDLE_EINTR(kevent(kq, &change, 1, &event, 1, spec_ptr));
796 if (close(kq) != 0) {
797 PLOG(ERROR) << "close";
798 }
799 if (event_count < 0) {
800 PLOG(ERROR) << "kevent";
801 return false;
802 } else if (event_count == 0) {
803 if (wait_milliseconds != base::kNoTimeout) {
804 // Timed out.
805 return false;
806 }
807 } else if ((event_count == 1) &&
808 (handle == static_cast<pid_t>(event.ident)) &&
809 (event.filter == EVFILT_PROC)) {
810 if (event.fflags == NOTE_EXIT) {
811 return true;
812 } else if (event.flags == EV_ERROR) {
813 LOG(ERROR) << "kevent error " << event.data;
814 return false;
815 } else {
816 NOTREACHED();
817 return false;
818 }
819 } else {
820 NOTREACHED();
821 return false;
822 }
823 }
824}
825#endif // OS_MACOSX
826
[email protected]743ace42009-06-17 17:23:51827bool WaitForSingleProcess(ProcessHandle handle, int64 wait_milliseconds) {
[email protected]56f0f262011-02-24 17:14:36828 ProcessHandle parent_pid = GetParentProcessId(handle);
829 ProcessHandle our_pid = Process::Current().handle();
830 if (parent_pid != our_pid) {
831#if defined(OS_MACOSX)
832 // On Mac we can wait on non child processes.
833 return WaitForSingleNonChildProcess(handle, wait_milliseconds);
834#else
835 // Currently on Linux we can't handle non child processes.
836 NOTIMPLEMENTED();
837#endif // OS_MACOSX
838 }
[email protected]eaec38c2010-11-29 19:30:23839 bool waitpid_success;
[email protected]45750212009-04-27 23:01:34840 int status;
[email protected]eaec38c2010-11-29 19:30:23841 if (wait_milliseconds == base::kNoTimeout)
842 waitpid_success = (HANDLE_EINTR(waitpid(handle, &status, 0)) != -1);
843 else
844 status = WaitpidWithTimeout(handle, wait_milliseconds, &waitpid_success);
845 if (status != -1) {
846 DCHECK(waitpid_success);
847 return WIFEXITED(status);
[email protected]ef0279272009-03-06 09:24:38848 } else {
[email protected]774f2202010-11-29 18:56:19849 return false;
[email protected]eaec38c2010-11-29 19:30:23850 }
[email protected]076bf0b62009-03-04 20:57:58851}
852
[email protected]0d83c732008-12-02 16:50:47853int64 TimeValToMicroseconds(const struct timeval& tv) {
[email protected]2d9bb0222010-04-02 08:24:01854 static const int kMicrosecondsPerSecond = 1000000;
855 int64 ret = tv.tv_sec; // Avoid (int * int) integer overflow.
856 ret *= kMicrosecondsPerSecond;
857 ret += tv.tv_usec;
858 return ret;
[email protected]0d83c732008-12-02 16:50:47859}
860
[email protected]3b9f5aa2010-07-28 04:02:34861// Executes the application specified by |cl| and wait for it to exit. Stores
862// the output (stdout) in |output|. If |do_search_path| is set, it searches the
[email protected]f164cea2009-11-05 23:37:40863// path for the application; in that case, |envp| must be null, and it will use
864// the current environment. If |do_search_path| is false, |cl| should fully
865// specify the path of the application, and |envp| will be used as the
866// environment. Redirects stderr to /dev/null. Returns true on success
867// (application launched and exited cleanly, with exit code indicating success).
[email protected]f164cea2009-11-05 23:37:40868static bool GetAppOutputInternal(const CommandLine& cl, char* const envp[],
869 std::string* output, size_t max_output,
[email protected]3b9f5aa2010-07-28 04:02:34870 bool do_search_path) {
[email protected]b42c4652010-12-04 03:23:53871 // Doing a blocking wait for another command to finish counts as IO.
872 base::ThreadRestrictions::AssertIOAllowed();
873
[email protected]c0b210ee2009-04-17 09:57:52874 int pipe_fd[2];
875 pid_t pid;
[email protected]ef73044e2010-03-11 15:25:54876 InjectiveMultimap fd_shuffle1, fd_shuffle2;
877 const std::vector<std::string>& argv = cl.argv();
878 scoped_array<char*> argv_cstr(new char*[argv.size() + 1]);
879
880 fd_shuffle1.reserve(3);
881 fd_shuffle2.reserve(3);
[email protected]c0b210ee2009-04-17 09:57:52882
[email protected]f164cea2009-11-05 23:37:40883 // Either |do_search_path| should be false or |envp| should be null, but not
884 // both.
885 DCHECK(!do_search_path ^ !envp);
886
[email protected]c0b210ee2009-04-17 09:57:52887 if (pipe(pipe_fd) < 0)
888 return false;
889
890 switch (pid = fork()) {
891 case -1: // error
892 close(pipe_fd[0]);
893 close(pipe_fd[1]);
894 return false;
895 case 0: // child
896 {
[email protected]e9a8c19f2009-09-03 21:27:36897#if defined(OS_MACOSX)
898 RestoreDefaultExceptionHandler();
899#endif
[email protected]ef73044e2010-03-11 15:25:54900 // DANGER: no calls to malloc are allowed from now on:
901 // http://crbug.com/36678
[email protected]e9a8c19f2009-09-03 21:27:36902
[email protected]afa82472009-07-23 19:11:48903 // Obscure fork() rule: in the child, if you don't end up doing exec*(),
904 // you call _exit() instead of exit(). This is because _exit() does not
905 // call any previously-registered (in the parent) exit handlers, which
906 // might do things like block waiting for threads that don't even exist
907 // in the child.
[email protected]1912cfe2009-04-21 08:09:30908 int dev_null = open("/dev/null", O_WRONLY);
909 if (dev_null < 0)
[email protected]7a97d292009-07-22 18:21:27910 _exit(127);
[email protected]1912cfe2009-04-21 08:09:30911
[email protected]ef73044e2010-03-11 15:25:54912 fd_shuffle1.push_back(InjectionArc(pipe_fd[1], STDOUT_FILENO, true));
913 fd_shuffle1.push_back(InjectionArc(dev_null, STDERR_FILENO, true));
914 fd_shuffle1.push_back(InjectionArc(dev_null, STDIN_FILENO, true));
[email protected]3b9f5aa2010-07-28 04:02:34915 // Adding another element here? Remeber to increase the argument to
[email protected]ef73044e2010-03-11 15:25:54916 // reserve(), above.
[email protected]3f04f2b2009-04-30 19:40:03917
[email protected]ef73044e2010-03-11 15:25:54918 std::copy(fd_shuffle1.begin(), fd_shuffle1.end(),
919 std::back_inserter(fd_shuffle2));
920
921 if (!ShuffleFileDescriptors(&fd_shuffle1))
[email protected]7a97d292009-07-22 18:21:27922 _exit(127);
[email protected]3f04f2b2009-04-30 19:40:03923
[email protected]ef73044e2010-03-11 15:25:54924 CloseSuperfluousFds(fd_shuffle2);
[email protected]c0b210ee2009-04-17 09:57:52925
[email protected]c0b210ee2009-04-17 09:57:52926 for (size_t i = 0; i < argv.size(); i++)
927 argv_cstr[i] = const_cast<char*>(argv[i].c_str());
928 argv_cstr[argv.size()] = NULL;
[email protected]f164cea2009-11-05 23:37:40929 if (do_search_path)
930 execvp(argv_cstr[0], argv_cstr.get());
931 else
932 execve(argv_cstr[0], argv_cstr.get(), envp);
[email protected]7a97d292009-07-22 18:21:27933 _exit(127);
[email protected]c0b210ee2009-04-17 09:57:52934 }
935 default: // parent
936 {
937 // Close our writing end of pipe now. Otherwise later read would not
938 // be able to detect end of child's output (in theory we could still
939 // write to the pipe).
940 close(pipe_fd[1]);
941
[email protected]96878a212010-06-10 18:26:33942 output->clear();
[email protected]c0b210ee2009-04-17 09:57:52943 char buffer[256];
[email protected]983ef7f2010-01-04 16:17:13944 size_t output_buf_left = max_output;
[email protected]f164cea2009-11-05 23:37:40945 ssize_t bytes_read = 1; // A lie to properly handle |max_output == 0|
946 // case in the logic below.
[email protected]c0b210ee2009-04-17 09:57:52947
[email protected]983ef7f2010-01-04 16:17:13948 while (output_buf_left > 0) {
[email protected]f164cea2009-11-05 23:37:40949 bytes_read = HANDLE_EINTR(read(pipe_fd[0], buffer,
[email protected]983ef7f2010-01-04 16:17:13950 std::min(output_buf_left, sizeof(buffer))));
[email protected]157c61b2009-05-01 21:37:31951 if (bytes_read <= 0)
[email protected]c0b210ee2009-04-17 09:57:52952 break;
[email protected]96878a212010-06-10 18:26:33953 output->append(buffer, bytes_read);
[email protected]983ef7f2010-01-04 16:17:13954 output_buf_left -= static_cast<size_t>(bytes_read);
[email protected]c0b210ee2009-04-17 09:57:52955 }
[email protected]c0b210ee2009-04-17 09:57:52956 close(pipe_fd[0]);
[email protected]affb1842009-06-10 16:56:31957
[email protected]3b9f5aa2010-07-28 04:02:34958 // Always wait for exit code (even if we know we'll declare success).
959 int exit_code = EXIT_FAILURE;
960 bool success = WaitForExitCode(pid, &exit_code);
[email protected]983ef7f2010-01-04 16:17:13961
[email protected]f164cea2009-11-05 23:37:40962 // If we stopped because we read as much as we wanted, we always declare
963 // success (because the child may exit due to |SIGPIPE|).
[email protected]983ef7f2010-01-04 16:17:13964 if (output_buf_left || bytes_read <= 0) {
[email protected]f164cea2009-11-05 23:37:40965 if (!success || exit_code != EXIT_SUCCESS)
966 return false;
967 }
[email protected]affb1842009-06-10 16:56:31968
[email protected]c0b210ee2009-04-17 09:57:52969 return true;
970 }
971 }
972}
973
[email protected]f164cea2009-11-05 23:37:40974bool GetAppOutput(const CommandLine& cl, std::string* output) {
975 // Run |execve()| with the current environment and store "unlimited" data.
976 return GetAppOutputInternal(cl, NULL, output,
[email protected]3b9f5aa2010-07-28 04:02:34977 std::numeric_limits<std::size_t>::max(), true);
[email protected]f164cea2009-11-05 23:37:40978}
979
[email protected]3b9f5aa2010-07-28 04:02:34980// TODO(viettrungluu): Conceivably, we should have a timeout as well, so we
981// don't hang if what we're calling hangs.
[email protected]f164cea2009-11-05 23:37:40982bool GetAppOutputRestricted(const CommandLine& cl,
983 std::string* output, size_t max_output) {
984 // Run |execve()| with the empty environment.
985 char* const empty_environ = NULL;
[email protected]3b9f5aa2010-07-28 04:02:34986 return GetAppOutputInternal(cl, &empty_environ, output, max_output, false);
[email protected]f164cea2009-11-05 23:37:40987}
988
[email protected]4f260d02010-12-23 18:35:42989bool WaitForProcessesToExit(const FilePath::StringType& executable_name,
[email protected]743ace42009-06-17 17:23:51990 int64 wait_milliseconds,
[email protected]962dd312009-02-05 21:44:13991 const ProcessFilter* filter) {
992 bool result = false;
993
994 // TODO(port): This is inefficient, but works if there are multiple procs.
995 // TODO(port): use waitpid to avoid leaving zombies around
996
997 base::Time end_time = base::Time::Now() +
998 base::TimeDelta::FromMilliseconds(wait_milliseconds);
999 do {
1000 NamedProcessIterator iter(executable_name, filter);
1001 if (!iter.NextProcessEntry()) {
1002 result = true;
1003 break;
1004 }
[email protected]ce072a72010-12-31 20:02:161005 base::PlatformThread::Sleep(100);
[email protected]1e932112011-06-29 20:53:221006 } while ((end_time - base::Time::Now()) > base::TimeDelta());
[email protected]962dd312009-02-05 21:44:131007
1008 return result;
1009}
1010
[email protected]4f260d02010-12-23 18:35:421011bool CleanupProcesses(const FilePath::StringType& executable_name,
[email protected]743ace42009-06-17 17:23:511012 int64 wait_milliseconds,
[email protected]962dd312009-02-05 21:44:131013 int exit_code,
1014 const ProcessFilter* filter) {
1015 bool exited_cleanly =
1016 WaitForProcessesToExit(executable_name, wait_milliseconds,
[email protected]743ace42009-06-17 17:23:511017 filter);
[email protected]962dd312009-02-05 21:44:131018 if (!exited_cleanly)
1019 KillProcesses(executable_name, exit_code, filter);
1020 return exited_cleanly;
1021}
1022
[email protected]aa660752008-11-14 03:39:461023} // namespace base