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) 2009 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 : // This file/namespace contains utility functions for enumerating, ending and
8 : // computing statistics of processes.
9 :
10 : #ifndef BASE_PROCESS_UTIL_H_
11 : #define BASE_PROCESS_UTIL_H_
12 :
13 : #include "base/basictypes.h"
14 :
15 : #if defined(OS_WIN)
16 : #include <windows.h>
17 : #include <tlhelp32.h>
18 : #include <io.h>
19 : #ifndef STDOUT_FILENO
20 : #define STDOUT_FILENO 1
21 : #endif
22 : #elif defined(OS_LINUX) || defined(__GLIBC__)
23 : #include <dirent.h>
24 : #include <limits.h>
25 : #include <sys/types.h>
26 : #elif defined(OS_MACOSX)
27 : #include <mach/mach.h>
28 : #endif
29 :
30 : #include <map>
31 : #include <string>
32 : #include <vector>
33 : #include <stdio.h>
34 : #include <stdlib.h>
35 : #ifndef OS_WIN
36 : #include <unistd.h>
37 : #endif
38 :
39 : #include "base/child_privileges.h"
40 : #include "base/command_line.h"
41 : #include "base/process.h"
42 :
43 : #if defined(OS_WIN)
44 : typedef PROCESSENTRY32 ProcessEntry;
45 : typedef IO_COUNTERS IoCounters;
46 : #elif defined(OS_POSIX)
47 : // TODO(port): we should not rely on a Win32 structure.
48 : struct ProcessEntry {
49 : int pid;
50 : int ppid;
51 : char szExeFile[_POSIX_PATH_MAX + 1];
52 : };
53 :
54 : struct IoCounters {
55 : unsigned long long ReadOperationCount;
56 : unsigned long long WriteOperationCount;
57 : unsigned long long OtherOperationCount;
58 : unsigned long long ReadTransferCount;
59 : unsigned long long WriteTransferCount;
60 : unsigned long long OtherTransferCount;
61 : };
62 :
63 : #include "base/file_descriptor_shuffle.h"
64 : #endif
65 :
66 : #if defined(OS_MACOSX)
67 : struct kinfo_proc;
68 : #endif
69 :
70 : namespace base {
71 :
72 : // These can be used in a 32-bit bitmask.
73 : enum ProcessArchitecture {
74 : PROCESS_ARCH_I386 = 0x1,
75 : PROCESS_ARCH_X86_64 = 0x2,
76 : PROCESS_ARCH_PPC = 0x4,
77 : PROCESS_ARCH_ARM = 0x8,
78 : PROCESS_ARCH_MIPS = 0x10,
79 : PROCESS_ARCH_ARM64 = 0x20
80 : };
81 :
82 4 : inline ProcessArchitecture GetCurrentProcessArchitecture()
83 : {
84 : base::ProcessArchitecture currentArchitecture;
85 : #if defined(ARCH_CPU_X86)
86 : currentArchitecture = base::PROCESS_ARCH_I386;
87 : #elif defined(ARCH_CPU_X86_64)
88 4 : currentArchitecture = base::PROCESS_ARCH_X86_64;
89 : #elif defined(ARCH_CPU_PPC)
90 : currentArchitecture = base::PROCESS_ARCH_PPC;
91 : #elif defined(ARCH_CPU_ARMEL)
92 : currentArchitecture = base::PROCESS_ARCH_ARM;
93 : #elif defined(ARCH_CPU_MIPS)
94 : currentArchitecture = base::PROCESS_ARCH_MIPS;
95 : #elif defined(ARCH_CPU_ARM64)
96 : currentArchitecture = base::PROCESS_ARCH_ARM64;
97 : #endif
98 4 : return currentArchitecture;
99 : }
100 :
101 : // A minimalistic but hopefully cross-platform set of exit codes.
102 : // Do not change the enumeration values or you will break third-party
103 : // installers.
104 : enum {
105 : PROCESS_END_NORMAL_TERMINATON = 0,
106 : PROCESS_END_KILLED_BY_USER = 1,
107 : PROCESS_END_PROCESS_WAS_HUNG = 2
108 : };
109 :
110 : // Returns the id of the current process.
111 : ProcessId GetCurrentProcId();
112 :
113 : // Returns the ProcessHandle of the current process.
114 : ProcessHandle GetCurrentProcessHandle();
115 :
116 : // Converts a PID to a process handle. This handle must be closed by
117 : // CloseProcessHandle when you are done with it. Returns true on success.
118 : bool OpenProcessHandle(ProcessId pid, ProcessHandle* handle);
119 :
120 : // Converts a PID to a process handle. On Windows the handle is opened
121 : // with more access rights and must only be used by trusted code.
122 : // You have to close returned handle using CloseProcessHandle. Returns true
123 : // on success.
124 : bool OpenPrivilegedProcessHandle(ProcessId pid, ProcessHandle* handle);
125 :
126 : // Closes the process handle opened by OpenProcessHandle.
127 : void CloseProcessHandle(ProcessHandle process);
128 :
129 : // Returns the unique ID for the specified process. This is functionally the
130 : // same as Windows' GetProcessId(), but works on versions of Windows before
131 : // Win XP SP1 as well.
132 : ProcessId GetProcId(ProcessHandle process);
133 :
134 : #if defined(OS_POSIX)
135 : // Sets all file descriptors to close on exec except for stdin, stdout
136 : // and stderr.
137 : // TODO(agl): remove this function
138 : // WARNING: do not use. It's inherently race-prone in the face of
139 : // multi-threading.
140 : void SetAllFDsToCloseOnExec();
141 : // Close all file descriptors, expect those which are a destination in the
142 : // given multimap. Only call this function in a child process where you know
143 : // that there aren't any other threads.
144 : void CloseSuperfluousFds(const base::InjectiveMultimap& saved_map);
145 : #endif
146 :
147 : #if defined(OS_WIN)
148 : // Runs the given application name with the given command line. Normally, the
149 : // first command line argument should be the path to the process, and don't
150 : // forget to quote it.
151 : //
152 : // If wait is true, it will block and wait for the other process to finish,
153 : // otherwise, it will just continue asynchronously.
154 : //
155 : // Example (including literal quotes)
156 : // cmdline = "c:\windows\explorer.exe" -foo "c:\bar\"
157 : //
158 : // If process_handle is non-NULL, the process handle of the launched app will be
159 : // stored there on a successful launch.
160 : // NOTE: In this case, the caller is responsible for closing the handle so
161 : // that it doesn't leak!
162 : bool LaunchApp(const std::wstring& cmdline,
163 : bool wait, bool start_hidden, ProcessHandle* process_handle);
164 : #elif defined(OS_POSIX)
165 : // Runs the application specified in argv[0] with the command line argv.
166 : // Before launching all FDs open in the parent process will be marked as
167 : // close-on-exec. |fds_to_remap| defines a mapping of src fd->dest fd to
168 : // propagate FDs into the child process.
169 : //
170 : // As above, if wait is true, execute synchronously. The pid will be stored
171 : // in process_handle if that pointer is non-null.
172 : //
173 : // Note that the first argument in argv must point to the filename,
174 : // and must be fully specified.
175 : typedef std::vector<std::pair<int, int> > file_handle_mapping_vector;
176 : bool LaunchApp(const std::vector<std::string>& argv,
177 : const file_handle_mapping_vector& fds_to_remap,
178 : bool wait, ProcessHandle* process_handle);
179 :
180 : typedef std::map<std::string, std::string> environment_map;
181 : bool LaunchApp(const std::vector<std::string>& argv,
182 : const file_handle_mapping_vector& fds_to_remap,
183 : const environment_map& env_vars_to_set,
184 : ChildPrivileges privs,
185 : bool wait, ProcessHandle* process_handle,
186 : ProcessArchitecture arch=GetCurrentProcessArchitecture());
187 : bool LaunchApp(const std::vector<std::string>& argv,
188 : const file_handle_mapping_vector& fds_to_remap,
189 : const environment_map& env_vars_to_set,
190 : bool wait, ProcessHandle* process_handle,
191 : ProcessArchitecture arch=GetCurrentProcessArchitecture());
192 : #endif
193 :
194 : // Adjust the privileges of this process to match |privs|. Only
195 : // returns if privileges were successfully adjusted.
196 : void SetCurrentProcessPrivileges(ChildPrivileges privs);
197 :
198 : // Executes the application specified by cl. This function delegates to one
199 : // of the above two platform-specific functions.
200 : bool LaunchApp(const CommandLine& cl,
201 : bool wait, bool start_hidden, ProcessHandle* process_handle);
202 :
203 : // Used to filter processes by process ID.
204 : class ProcessFilter {
205 : public:
206 : // Returns true to indicate set-inclusion and false otherwise. This method
207 : // should not have side-effects and should be idempotent.
208 : virtual bool Includes(ProcessId pid, ProcessId parent_pid) const = 0;
209 : virtual ~ProcessFilter() { }
210 : };
211 :
212 : // Attempts to kill the process identified by the given process
213 : // entry structure, giving it the specified exit code. If |wait| is true, wait
214 : // for the process to be actually terminated before returning.
215 : // Returns true if this is successful, false otherwise.
216 : bool KillProcess(ProcessHandle process, int exit_code, bool wait);
217 :
218 : // Get the termination status (exit code) of the process and return true if the
219 : // status indicates the process crashed. |child_exited| is set to true iff the
220 : // child process has terminated. (|child_exited| may be NULL.)
221 : //
222 : // On Windows, it is an error to call this if the process hasn't terminated
223 : // yet. On POSIX, |child_exited| is set correctly since we detect terminate in
224 : // a different manner on POSIX.
225 : bool DidProcessCrash(bool* child_exited, ProcessHandle handle);
226 :
227 : // Provides performance metrics for a specified process (CPU usage, memory and
228 : // IO counters). To use it, invoke CreateProcessMetrics() to get an instance
229 : // for a specific process, then access the information with the different get
230 : // methods.
231 : class ProcessMetrics {
232 : public:
233 : // Creates a ProcessMetrics for the specified process.
234 : // The caller owns the returned object.
235 : static ProcessMetrics* CreateProcessMetrics(ProcessHandle process);
236 :
237 : ~ProcessMetrics();
238 :
239 : // Returns the CPU usage in percent since the last time this method was
240 : // called. The first time this method is called it returns 0 and will return
241 : // the actual CPU info on subsequent calls.
242 : // Note that on multi-processor machines, the CPU usage value is for all
243 : // CPUs. So if you have 2 CPUs and your process is using all the cycles
244 : // of 1 CPU and not the other CPU, this method returns 50.
245 : int GetCPUUsage();
246 :
247 : private:
248 : explicit ProcessMetrics(ProcessHandle process);
249 :
250 : ProcessHandle process_;
251 :
252 : int processor_count_;
253 :
254 : // Used to store the previous times so we can compute the CPU usage.
255 : int64_t last_time_;
256 : int64_t last_system_time_;
257 :
258 : DISALLOW_EVIL_CONSTRUCTORS(ProcessMetrics);
259 : };
260 :
261 : } // namespace base
262 :
263 : namespace mozilla {
264 :
265 : class EnvironmentLog
266 : {
267 : public:
268 3 : explicit EnvironmentLog(const char* varname) {
269 3 : const char *e = getenv(varname);
270 3 : if (e && *e) {
271 0 : fname_ = e;
272 : }
273 3 : }
274 :
275 0 : ~EnvironmentLog() {}
276 :
277 3 : void print(const char* format, ...) {
278 3 : if (!fname_.size())
279 6 : return;
280 :
281 : FILE* f;
282 0 : if (fname_.compare("-") == 0) {
283 0 : f = fdopen(dup(STDOUT_FILENO), "a");
284 : } else {
285 0 : f = fopen(fname_.c_str(), "a");
286 : }
287 :
288 0 : if (!f)
289 0 : return;
290 :
291 : va_list a;
292 0 : va_start(a, format);
293 0 : vfprintf(f, format, a);
294 0 : va_end(a);
295 0 : fclose(f);
296 : }
297 :
298 : private:
299 : std::string fname_;
300 :
301 : DISALLOW_EVIL_CONSTRUCTORS(EnvironmentLog);
302 : };
303 :
304 : } // namespace mozilla
305 :
306 : #if defined(OS_WIN)
307 : // Undo the windows.h damage
308 : #undef GetMessage
309 : #undef CreateEvent
310 : #undef GetClassName
311 : #undef GetBinaryType
312 : #undef RemoveDirectory
313 : #endif
314 :
315 : #endif // BASE_PROCESS_UTIL_H_
|