LCOV - code coverage report
Current view: top level - ipc/chromium/src/base - process_util_posix.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 11 152 7.2 %
Date: 2017-07-14 16:53:18 Functions: 5 16 31.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
       4             : // Use of this source code is governed by a BSD-style license that can be
       5             : // found in the LICENSE file.
       6             : 
       7             : #include <dirent.h>
       8             : #include <errno.h>
       9             : #include <fcntl.h>
      10             : #include <signal.h>
      11             : #include <stdlib.h>
      12             : #include <sys/resource.h>
      13             : #include <sys/time.h>
      14             : #include <sys/types.h>
      15             : #include <sys/wait.h>
      16             : #include <unistd.h>
      17             : 
      18             : #include <limits>
      19             : #include <set>
      20             : 
      21             : #include "base/basictypes.h"
      22             : #include "base/eintr_wrapper.h"
      23             : #include "base/logging.h"
      24             : #include "base/platform_thread.h"
      25             : #include "base/process_util.h"
      26             : #include "base/sys_info.h"
      27             : #include "base/time.h"
      28             : #include "base/waitable_event.h"
      29             : #include "base/dir_reader_posix.h"
      30             : 
      31             : #include "mozilla/UniquePtr.h"
      32             : 
      33             : const int kMicrosecondsPerSecond = 1000000;
      34             : 
      35             : namespace base {
      36             : 
      37         198 : ProcessId GetCurrentProcId() {
      38         198 :   return getpid();
      39             : }
      40             : 
      41           2 : ProcessHandle GetCurrentProcessHandle() {
      42           2 :   return GetCurrentProcId();
      43             : }
      44             : 
      45           2 : bool OpenProcessHandle(ProcessId pid, ProcessHandle* handle) {
      46             :   // On Posix platforms, process handles are the same as PIDs, so we
      47             :   // don't need to do anything.
      48           2 :   *handle = pid;
      49           2 :   return true;
      50             : }
      51             : 
      52           2 : bool OpenPrivilegedProcessHandle(ProcessId pid, ProcessHandle* handle) {
      53             :   // On POSIX permissions are checked for each operation on process,
      54             :   // not when opening a "handle".
      55           2 :   return OpenProcessHandle(pid, handle);
      56             : }
      57             : 
      58           0 : void CloseProcessHandle(ProcessHandle process) {
      59             :   // See OpenProcessHandle, nothing to do.
      60           0 :   return;
      61             : }
      62             : 
      63           8 : ProcessId GetProcId(ProcessHandle process) {
      64           8 :   return process;
      65             : }
      66             : 
      67             : // Attempts to kill the process identified by the given process
      68             : // entry structure.  Ignores specified exit_code; posix can't force that.
      69             : // Returns true if this is successful, false otherwise.
      70           0 : bool KillProcess(ProcessHandle process_id, int exit_code, bool wait) {
      71           0 :   bool result = kill(process_id, SIGTERM) == 0;
      72             : 
      73           0 :   if (!result && (errno == ESRCH)) {
      74           0 :     result = true;
      75           0 :     wait = false;
      76             :   }
      77             : 
      78           0 :   if (result && wait) {
      79           0 :     int tries = 60;
      80           0 :     bool exited = false;
      81             :     // The process may not end immediately due to pending I/O
      82           0 :     while (tries-- > 0) {
      83           0 :       int pid = HANDLE_EINTR(waitpid(process_id, NULL, WNOHANG));
      84           0 :       if (pid == process_id) {
      85           0 :         exited = true;
      86           0 :         break;
      87           0 :       } else if (errno == ECHILD) {
      88           0 :         exited = true;
      89           0 :         break;
      90             :       }
      91             : 
      92           0 :       sleep(1);
      93             :     }
      94             : 
      95           0 :     if (!exited) {
      96           0 :       result = kill(process_id, SIGKILL) == 0;
      97             :     }
      98             :   }
      99             : 
     100           0 :   if (!result)
     101           0 :     DLOG(ERROR) << "Unable to terminate process.";
     102             : 
     103           0 :   return result;
     104             : }
     105             : 
     106             : #ifdef ANDROID
     107             : typedef unsigned long int rlim_t;
     108             : #endif
     109             : 
     110             : // A class to handle auto-closing of DIR*'s.
     111             : class ScopedDIRClose {
     112             :  public:
     113           0 :   inline void operator()(DIR* x) const {
     114           0 :     if (x) {
     115           0 :       closedir(x);
     116             :     }
     117           0 :   }
     118             : };
     119             : typedef mozilla::UniquePtr<DIR, ScopedDIRClose> ScopedDIR;
     120             : 
     121             : 
     122           0 : void CloseSuperfluousFds(const base::InjectiveMultimap& saved_mapping) {
     123             :   // DANGER: no calls to malloc are allowed from now on:
     124             :   // http://crbug.com/36678
     125             : #if defined(ANDROID)
     126             :   static const rlim_t kSystemDefaultMaxFds = 1024;
     127             :   static const char kFDDir[] = "/proc/self/fd";
     128             : #elif defined(OS_LINUX) || defined(OS_SOLARIS)
     129             :   static const rlim_t kSystemDefaultMaxFds = 8192;
     130             :   static const char kFDDir[] = "/proc/self/fd";
     131             : #elif defined(OS_MACOSX)
     132             :   static const rlim_t kSystemDefaultMaxFds = 256;
     133             :   static const char kFDDir[] = "/dev/fd";
     134             : #elif defined(OS_BSD)
     135             :   // the getrlimit below should never fail, so whatever ..
     136             :   static const rlim_t kSystemDefaultMaxFds = 1024;
     137             :   // at least /dev/fd will exist
     138             :   static const char kFDDir[] = "/dev/fd";
     139             : #endif
     140             : 
     141             :   // Get the maximum number of FDs possible.
     142             :   struct rlimit nofile;
     143             :   rlim_t max_fds;
     144           0 :   if (getrlimit(RLIMIT_NOFILE, &nofile)) {
     145             :     // getrlimit failed. Take a best guess.
     146           0 :     max_fds = kSystemDefaultMaxFds;
     147           0 :     DLOG(ERROR) << "getrlimit(RLIMIT_NOFILE) failed: " << errno;
     148             :   } else {
     149           0 :     max_fds = nofile.rlim_cur;
     150             :   }
     151             : 
     152           0 :   if (max_fds > INT_MAX)
     153           0 :     max_fds = INT_MAX;
     154             : 
     155           0 :   DirReaderPosix fd_dir(kFDDir);
     156             : 
     157           0 :   if (!fd_dir.IsValid()) {
     158             :     // Fallback case: Try every possible fd.
     159           0 :     for (rlim_t i = 0; i < max_fds; ++i) {
     160           0 :       const int fd = static_cast<int>(i);
     161           0 :       if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO)
     162           0 :         continue;
     163           0 :       InjectiveMultimap::const_iterator j;
     164           0 :       for (j = saved_mapping.begin(); j != saved_mapping.end(); j++) {
     165           0 :         if (fd == j->dest)
     166           0 :           break;
     167             :       }
     168           0 :       if (j != saved_mapping.end())
     169           0 :         continue;
     170             : 
     171             :       // Since we're just trying to close anything we can find,
     172             :       // ignore any error return values of close().
     173           0 :       HANDLE_EINTR(close(fd));
     174             :     }
     175           0 :     return;
     176             :   }
     177             : 
     178           0 :   const int dir_fd = fd_dir.fd();
     179             : 
     180           0 :   for ( ; fd_dir.Next(); ) {
     181             :     // Skip . and .. entries.
     182           0 :     if (fd_dir.name()[0] == '.')
     183           0 :       continue;
     184             : 
     185             :     char *endptr;
     186           0 :     errno = 0;
     187           0 :     const long int fd = strtol(fd_dir.name(), &endptr, 10);
     188           0 :     if (fd_dir.name()[0] == 0 || *endptr || fd < 0 || errno)
     189           0 :       continue;
     190           0 :     if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO)
     191           0 :       continue;
     192           0 :     InjectiveMultimap::const_iterator i;
     193           0 :     for (i = saved_mapping.begin(); i != saved_mapping.end(); i++) {
     194           0 :       if (fd == i->dest)
     195           0 :         break;
     196             :     }
     197           0 :     if (i != saved_mapping.end())
     198           0 :       continue;
     199           0 :     if (fd == dir_fd)
     200           0 :       continue;
     201             : 
     202             :     // When running under Valgrind, Valgrind opens several FDs for its
     203             :     // own use and will complain if we try to close them.  All of
     204             :     // these FDs are >= |max_fds|, so we can check against that here
     205             :     // before closing.  See https://bugs.kde.org/show_bug.cgi?id=191758
     206           0 :     if (fd < static_cast<int>(max_fds)) {
     207           0 :       int ret = HANDLE_EINTR(close(fd));
     208           0 :       if (ret != 0) {
     209           0 :         DLOG(ERROR) << "Problem closing fd";
     210             :       }
     211             :     }
     212             :   }
     213             : }
     214             : 
     215             : // Sets all file descriptors to close on exec except for stdin, stdout
     216             : // and stderr.
     217             : // TODO(agl): Remove this function. It's fundamentally broken for multithreaded
     218             : // apps.
     219           0 : void SetAllFDsToCloseOnExec() {
     220             : #if defined(OS_LINUX) || defined(OS_SOLARIS)
     221           0 :   const char fd_dir[] = "/proc/self/fd";
     222             : #elif defined(OS_MACOSX) || defined(OS_BSD)
     223             :   const char fd_dir[] = "/dev/fd";
     224             : #endif
     225           0 :   ScopedDIR dir_closer(opendir(fd_dir));
     226           0 :   DIR *dir = dir_closer.get();
     227           0 :   if (NULL == dir) {
     228           0 :     DLOG(ERROR) << "Unable to open " << fd_dir;
     229           0 :     return;
     230             :   }
     231             : 
     232             :   struct dirent *ent;
     233           0 :   while ((ent = readdir(dir))) {
     234             :     // Skip . and .. entries.
     235           0 :     if (ent->d_name[0] == '.')
     236           0 :       continue;
     237           0 :     int i = atoi(ent->d_name);
     238             :     // We don't close stdin, stdout or stderr.
     239           0 :     if (i <= STDERR_FILENO)
     240           0 :       continue;
     241             : 
     242           0 :     int flags = fcntl(i, F_GETFD);
     243           0 :     if ((flags == -1) || (fcntl(i, F_SETFD, flags | FD_CLOEXEC) == -1)) {
     244           0 :       DLOG(ERROR) << "fcntl failure.";
     245             :     }
     246             :   }
     247             : }
     248             : 
     249           0 : ProcessMetrics::ProcessMetrics(ProcessHandle process) : process_(process),
     250             :                                                         last_time_(0),
     251           0 :                                                         last_system_time_(0) {
     252           0 :   processor_count_ = base::SysInfo::NumberOfProcessors();
     253           0 : }
     254             : 
     255             : // static
     256           0 : ProcessMetrics* ProcessMetrics::CreateProcessMetrics(ProcessHandle process) {
     257           0 :   return new ProcessMetrics(process);
     258             : }
     259             : 
     260           0 : ProcessMetrics::~ProcessMetrics() { }
     261             : 
     262           0 : bool DidProcessCrash(bool* child_exited, ProcessHandle handle) {
     263             :   int status;
     264           0 :   const int result = HANDLE_EINTR(waitpid(handle, &status, WNOHANG));
     265           0 :   if (result == -1) {
     266             :     // This shouldn't happen, but sometimes it does.  The error is
     267             :     // probably ECHILD and the reason is probably that a pid was
     268             :     // waited on again after a previous wait reclaimed its zombie.
     269             :     // (It could also occur if the process isn't a direct child, but
     270             :     // don't do that.)  This is bad, because it risks interfering with
     271             :     // an unrelated child process if the pid is reused.
     272             :     //
     273             :     // So, lacking reliable information, we indicate that the process
     274             :     // is dead, in the hope that the caller will give up and stop
     275             :     // calling us.  See also bug 943174 and bug 933680.
     276           0 :     CHROMIUM_LOG(ERROR) << "waitpid failed pid:" << handle << " errno:" << errno;
     277           0 :     if (child_exited)
     278           0 :       *child_exited = true;
     279           0 :     return false;
     280           0 :   } else if (result == 0) {
     281             :     // the child hasn't exited yet.
     282           0 :     if (child_exited)
     283           0 :       *child_exited = false;
     284           0 :     return false;
     285             :   }
     286             : 
     287           0 :   if (child_exited)
     288           0 :     *child_exited = true;
     289             : 
     290           0 :   if (WIFSIGNALED(status)) {
     291           0 :     switch(WTERMSIG(status)) {
     292             :       case SIGSYS:
     293             :       case SIGSEGV:
     294             :       case SIGILL:
     295             :       case SIGABRT:
     296             :       case SIGFPE:
     297           0 :         return true;
     298             :       default:
     299           0 :         return false;
     300             :     }
     301             :   }
     302             : 
     303           0 :   if (WIFEXITED(status))
     304           0 :     return WEXITSTATUS(status) != 0;
     305             : 
     306           0 :   return false;
     307             : }
     308             : 
     309             : namespace {
     310             : 
     311           0 : int64_t TimeValToMicroseconds(const struct timeval& tv) {
     312           0 :   return tv.tv_sec * kMicrosecondsPerSecond + tv.tv_usec;
     313             : }
     314             : 
     315             : }
     316             : 
     317           0 : int ProcessMetrics::GetCPUUsage() {
     318             :   struct timeval now;
     319             :   struct rusage usage;
     320             : 
     321           0 :   int retval = gettimeofday(&now, NULL);
     322           0 :   if (retval)
     323           0 :     return 0;
     324           0 :   retval = getrusage(RUSAGE_SELF, &usage);
     325           0 :   if (retval)
     326           0 :     return 0;
     327             : 
     328           0 :   int64_t system_time = (TimeValToMicroseconds(usage.ru_stime) +
     329           0 :                        TimeValToMicroseconds(usage.ru_utime)) /
     330           0 :                         processor_count_;
     331           0 :   int64_t time = TimeValToMicroseconds(now);
     332             : 
     333           0 :   if ((last_system_time_ == 0) || (last_time_ == 0)) {
     334             :     // First call, just set the last values.
     335           0 :     last_system_time_ = system_time;
     336           0 :     last_time_ = time;
     337           0 :     return 0;
     338             :   }
     339             : 
     340           0 :   int64_t system_time_delta = system_time - last_system_time_;
     341           0 :   int64_t time_delta = time - last_time_;
     342           0 :   DCHECK(time_delta != 0);
     343           0 :   if (time_delta == 0)
     344           0 :     return 0;
     345             : 
     346             :   // We add time_delta / 2 so the result is rounded.
     347           0 :   int cpu = static_cast<int>((system_time_delta * 100 + time_delta / 2) /
     348           0 :                              time_delta);
     349             : 
     350           0 :   last_system_time_ = system_time;
     351           0 :   last_time_ = time;
     352             : 
     353           0 :   return cpu;
     354             : }
     355             : 
     356             : }  // namespace base

Generated by: LCOV version 1.13