1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/chromium/src/base/process_util_posix.cc Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,341 @@ 1.4 +//* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1.6 +// Use of this source code is governed by a BSD-style license that can be 1.7 +// found in the LICENSE file. 1.8 + 1.9 +#include <dirent.h> 1.10 +#include <errno.h> 1.11 +#include <fcntl.h> 1.12 +#include <signal.h> 1.13 +#include <stdlib.h> 1.14 +#include <sys/resource.h> 1.15 +#include <sys/time.h> 1.16 +#include <sys/types.h> 1.17 +#include <sys/wait.h> 1.18 +#include <unistd.h> 1.19 + 1.20 +#include <limits> 1.21 +#include <set> 1.22 + 1.23 +#include "base/basictypes.h" 1.24 +#include "base/eintr_wrapper.h" 1.25 +#include "base/logging.h" 1.26 +#include "base/platform_thread.h" 1.27 +#include "base/process_util.h" 1.28 +#include "base/scoped_ptr.h" 1.29 +#include "base/sys_info.h" 1.30 +#include "base/time.h" 1.31 +#include "base/waitable_event.h" 1.32 +#include "base/dir_reader_posix.h" 1.33 + 1.34 +const int kMicrosecondsPerSecond = 1000000; 1.35 + 1.36 +namespace base { 1.37 + 1.38 +ProcessId GetCurrentProcId() { 1.39 + return getpid(); 1.40 +} 1.41 + 1.42 +ProcessHandle GetCurrentProcessHandle() { 1.43 + return GetCurrentProcId(); 1.44 +} 1.45 + 1.46 +bool OpenProcessHandle(ProcessId pid, ProcessHandle* handle) { 1.47 + // On Posix platforms, process handles are the same as PIDs, so we 1.48 + // don't need to do anything. 1.49 + *handle = pid; 1.50 + return true; 1.51 +} 1.52 + 1.53 +bool OpenPrivilegedProcessHandle(ProcessId pid, ProcessHandle* handle) { 1.54 + // On POSIX permissions are checked for each operation on process, 1.55 + // not when opening a "handle". 1.56 + return OpenProcessHandle(pid, handle); 1.57 +} 1.58 + 1.59 +void CloseProcessHandle(ProcessHandle process) { 1.60 + // See OpenProcessHandle, nothing to do. 1.61 + return; 1.62 +} 1.63 + 1.64 +ProcessId GetProcId(ProcessHandle process) { 1.65 + return process; 1.66 +} 1.67 + 1.68 +// Attempts to kill the process identified by the given process 1.69 +// entry structure. Ignores specified exit_code; posix can't force that. 1.70 +// Returns true if this is successful, false otherwise. 1.71 +bool KillProcess(ProcessHandle process_id, int exit_code, bool wait) { 1.72 + bool result = kill(process_id, SIGTERM) == 0; 1.73 + 1.74 + if (result && wait) { 1.75 + int tries = 60; 1.76 + // The process may not end immediately due to pending I/O 1.77 + while (tries-- > 0) { 1.78 + int pid = HANDLE_EINTR(waitpid(process_id, NULL, WNOHANG)); 1.79 + if (pid == process_id) 1.80 + break; 1.81 + 1.82 + sleep(1); 1.83 + } 1.84 + 1.85 + result = kill(process_id, SIGKILL) == 0; 1.86 + } 1.87 + 1.88 + if (!result) 1.89 + DLOG(ERROR) << "Unable to terminate process."; 1.90 + 1.91 + return result; 1.92 +} 1.93 + 1.94 +#ifdef ANDROID 1.95 +typedef unsigned long int rlim_t; 1.96 +#endif 1.97 + 1.98 +// A class to handle auto-closing of DIR*'s. 1.99 +class ScopedDIRClose { 1.100 + public: 1.101 + inline void operator()(DIR* x) const { 1.102 + if (x) { 1.103 + closedir(x); 1.104 + } 1.105 + } 1.106 +}; 1.107 +typedef scoped_ptr_malloc<DIR, ScopedDIRClose> ScopedDIR; 1.108 + 1.109 + 1.110 +void CloseSuperfluousFds(const base::InjectiveMultimap& saved_mapping) { 1.111 + // DANGER: no calls to malloc are allowed from now on: 1.112 + // http://crbug.com/36678 1.113 +#if defined(ANDROID) 1.114 + static const rlim_t kSystemDefaultMaxFds = 1024; 1.115 + static const char kFDDir[] = "/proc/self/fd"; 1.116 +#elif defined(OS_LINUX) 1.117 + static const rlim_t kSystemDefaultMaxFds = 8192; 1.118 + static const char kFDDir[] = "/proc/self/fd"; 1.119 +#elif defined(OS_MACOSX) 1.120 + static const rlim_t kSystemDefaultMaxFds = 256; 1.121 + static const char kFDDir[] = "/dev/fd"; 1.122 +#elif defined(OS_BSD) 1.123 + // the getrlimit below should never fail, so whatever .. 1.124 + static const rlim_t kSystemDefaultMaxFds = 1024; 1.125 + // at least /dev/fd will exist 1.126 + static const char kFDDir[] = "/dev/fd"; 1.127 +#endif 1.128 + 1.129 + // Get the maximum number of FDs possible. 1.130 + struct rlimit nofile; 1.131 + rlim_t max_fds; 1.132 + if (getrlimit(RLIMIT_NOFILE, &nofile)) { 1.133 + // getrlimit failed. Take a best guess. 1.134 + max_fds = kSystemDefaultMaxFds; 1.135 + DLOG(ERROR) << "getrlimit(RLIMIT_NOFILE) failed: " << errno; 1.136 + } else { 1.137 + max_fds = nofile.rlim_cur; 1.138 + } 1.139 + 1.140 + if (max_fds > INT_MAX) 1.141 + max_fds = INT_MAX; 1.142 + 1.143 + DirReaderPosix fd_dir(kFDDir); 1.144 + 1.145 + if (!fd_dir.IsValid()) { 1.146 + // Fallback case: Try every possible fd. 1.147 + for (rlim_t i = 0; i < max_fds; ++i) { 1.148 + const int fd = static_cast<int>(i); 1.149 + if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO) 1.150 + continue; 1.151 + InjectiveMultimap::const_iterator j; 1.152 + for (j = saved_mapping.begin(); j != saved_mapping.end(); j++) { 1.153 + if (fd == j->dest) 1.154 + break; 1.155 + } 1.156 + if (j != saved_mapping.end()) 1.157 + continue; 1.158 + 1.159 + // Since we're just trying to close anything we can find, 1.160 + // ignore any error return values of close(). 1.161 + HANDLE_EINTR(close(fd)); 1.162 + } 1.163 + return; 1.164 + } 1.165 + 1.166 + const int dir_fd = fd_dir.fd(); 1.167 + 1.168 + for ( ; fd_dir.Next(); ) { 1.169 + // Skip . and .. entries. 1.170 + if (fd_dir.name()[0] == '.') 1.171 + continue; 1.172 + 1.173 + char *endptr; 1.174 + errno = 0; 1.175 + const long int fd = strtol(fd_dir.name(), &endptr, 10); 1.176 + if (fd_dir.name()[0] == 0 || *endptr || fd < 0 || errno) 1.177 + continue; 1.178 + if (fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO) 1.179 + continue; 1.180 + InjectiveMultimap::const_iterator i; 1.181 + for (i = saved_mapping.begin(); i != saved_mapping.end(); i++) { 1.182 + if (fd == i->dest) 1.183 + break; 1.184 + } 1.185 + if (i != saved_mapping.end()) 1.186 + continue; 1.187 + if (fd == dir_fd) 1.188 + continue; 1.189 + 1.190 + // When running under Valgrind, Valgrind opens several FDs for its 1.191 + // own use and will complain if we try to close them. All of 1.192 + // these FDs are >= |max_fds|, so we can check against that here 1.193 + // before closing. See https://bugs.kde.org/show_bug.cgi?id=191758 1.194 + if (fd < static_cast<int>(max_fds)) { 1.195 + int ret = HANDLE_EINTR(close(fd)); 1.196 + if (ret != 0) { 1.197 + DLOG(ERROR) << "Problem closing fd"; 1.198 + } 1.199 + } 1.200 + } 1.201 +} 1.202 + 1.203 +// Sets all file descriptors to close on exec except for stdin, stdout 1.204 +// and stderr. 1.205 +// TODO(agl): Remove this function. It's fundamentally broken for multithreaded 1.206 +// apps. 1.207 +void SetAllFDsToCloseOnExec() { 1.208 +#if defined(OS_LINUX) 1.209 + const char fd_dir[] = "/proc/self/fd"; 1.210 +#elif defined(OS_MACOSX) || defined(OS_BSD) 1.211 + const char fd_dir[] = "/dev/fd"; 1.212 +#endif 1.213 + ScopedDIR dir_closer(opendir(fd_dir)); 1.214 + DIR *dir = dir_closer.get(); 1.215 + if (NULL == dir) { 1.216 + DLOG(ERROR) << "Unable to open " << fd_dir; 1.217 + return; 1.218 + } 1.219 + 1.220 + struct dirent *ent; 1.221 + while ((ent = readdir(dir))) { 1.222 + // Skip . and .. entries. 1.223 + if (ent->d_name[0] == '.') 1.224 + continue; 1.225 + int i = atoi(ent->d_name); 1.226 + // We don't close stdin, stdout or stderr. 1.227 + if (i <= STDERR_FILENO) 1.228 + continue; 1.229 + 1.230 + int flags = fcntl(i, F_GETFD); 1.231 + if ((flags == -1) || (fcntl(i, F_SETFD, flags | FD_CLOEXEC) == -1)) { 1.232 + DLOG(ERROR) << "fcntl failure."; 1.233 + } 1.234 + } 1.235 +} 1.236 + 1.237 +ProcessMetrics::ProcessMetrics(ProcessHandle process) : process_(process), 1.238 + last_time_(0), 1.239 + last_system_time_(0) { 1.240 + processor_count_ = base::SysInfo::NumberOfProcessors(); 1.241 +} 1.242 + 1.243 +// static 1.244 +ProcessMetrics* ProcessMetrics::CreateProcessMetrics(ProcessHandle process) { 1.245 + return new ProcessMetrics(process); 1.246 +} 1.247 + 1.248 +ProcessMetrics::~ProcessMetrics() { } 1.249 + 1.250 +bool DidProcessCrash(bool* child_exited, ProcessHandle handle) { 1.251 + int status; 1.252 + const int result = HANDLE_EINTR(waitpid(handle, &status, WNOHANG)); 1.253 + if (result == -1) { 1.254 + // This shouldn't happen, but sometimes it does. The error is 1.255 + // probably ECHILD and the reason is probably that a pid was 1.256 + // waited on again after a previous wait reclaimed its zombie. 1.257 + // (It could also occur if the process isn't a direct child, but 1.258 + // don't do that.) This is bad, because it risks interfering with 1.259 + // an unrelated child process if the pid is reused. 1.260 + // 1.261 + // So, lacking reliable information, we indicate that the process 1.262 + // is dead, in the hope that the caller will give up and stop 1.263 + // calling us. See also bug 943174 and bug 933680. 1.264 + CHROMIUM_LOG(ERROR) << "waitpid failed pid:" << handle << " errno:" << errno; 1.265 + if (child_exited) 1.266 + *child_exited = true; 1.267 + return false; 1.268 + } else if (result == 0) { 1.269 + // the child hasn't exited yet. 1.270 + if (child_exited) 1.271 + *child_exited = false; 1.272 + return false; 1.273 + } 1.274 + 1.275 + if (child_exited) 1.276 + *child_exited = true; 1.277 + 1.278 + if (WIFSIGNALED(status)) { 1.279 + switch(WTERMSIG(status)) { 1.280 + case SIGSYS: 1.281 + case SIGSEGV: 1.282 + case SIGILL: 1.283 + case SIGABRT: 1.284 + case SIGFPE: 1.285 + return true; 1.286 + default: 1.287 + return false; 1.288 + } 1.289 + } 1.290 + 1.291 + if (WIFEXITED(status)) 1.292 + return WEXITSTATUS(status) != 0; 1.293 + 1.294 + return false; 1.295 +} 1.296 + 1.297 +namespace { 1.298 + 1.299 +int64_t TimeValToMicroseconds(const struct timeval& tv) { 1.300 + return tv.tv_sec * kMicrosecondsPerSecond + tv.tv_usec; 1.301 +} 1.302 + 1.303 +} 1.304 + 1.305 +int ProcessMetrics::GetCPUUsage() { 1.306 + struct timeval now; 1.307 + struct rusage usage; 1.308 + 1.309 + int retval = gettimeofday(&now, NULL); 1.310 + if (retval) 1.311 + return 0; 1.312 + retval = getrusage(RUSAGE_SELF, &usage); 1.313 + if (retval) 1.314 + return 0; 1.315 + 1.316 + int64_t system_time = (TimeValToMicroseconds(usage.ru_stime) + 1.317 + TimeValToMicroseconds(usage.ru_utime)) / 1.318 + processor_count_; 1.319 + int64_t time = TimeValToMicroseconds(now); 1.320 + 1.321 + if ((last_system_time_ == 0) || (last_time_ == 0)) { 1.322 + // First call, just set the last values. 1.323 + last_system_time_ = system_time; 1.324 + last_time_ = time; 1.325 + return 0; 1.326 + } 1.327 + 1.328 + int64_t system_time_delta = system_time - last_system_time_; 1.329 + int64_t time_delta = time - last_time_; 1.330 + DCHECK(time_delta != 0); 1.331 + if (time_delta == 0) 1.332 + return 0; 1.333 + 1.334 + // We add time_delta / 2 so the result is rounded. 1.335 + int cpu = static_cast<int>((system_time_delta * 100 + time_delta / 2) / 1.336 + time_delta); 1.337 + 1.338 + last_system_time_ = system_time; 1.339 + last_time_ = time; 1.340 + 1.341 + return cpu; 1.342 +} 1.343 + 1.344 +} // namespace base