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