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