ipc/chromium/src/base/process_util.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial