process_util.h (9494B)
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(XP_WIN) 16 # include "mozilla/ipc/EnvironmentMap.h" 17 # include <windows.h> 18 # include <tlhelp32.h> 19 #elif defined(XP_LINUX) || defined(__GLIBC__) 20 # include <dirent.h> 21 # include <limits.h> 22 # include <sys/types.h> 23 #elif defined(XP_DARWIN) 24 # include <mach/mach.h> 25 #endif 26 27 #include <cstddef> 28 #include <map> 29 #include <string> 30 #include <utility> 31 #include <vector> 32 33 #include "base/process.h" 34 35 #include "mozilla/UniquePtr.h" 36 #include "mozilla/UniquePtrExtensions.h" 37 #include "mozilla/Result.h" 38 #include "mozilla/ResultVariant.h" 39 40 #include "mozilla/ipc/LaunchError.h" 41 42 #if defined(XP_DARWIN) 43 struct kinfo_proc; 44 #endif 45 46 class CommandLine; 47 48 namespace base { 49 50 using mozilla::Err; 51 using mozilla::Ok; 52 using mozilla::Result; 53 using mozilla::ipc::LaunchError; 54 55 enum ProcessArchitecture { 56 PROCESS_ARCH_INVALID = 0x0, 57 PROCESS_ARCH_I386 = 0x1, 58 PROCESS_ARCH_X86_64 = 0x2, 59 PROCESS_ARCH_PPC = 0x4, 60 PROCESS_ARCH_PPC_64 = 0x8, 61 PROCESS_ARCH_ARM = 0x10, 62 PROCESS_ARCH_ARM_64 = 0x20 63 }; 64 65 // A minimalistic but hopefully cross-platform set of exit codes. 66 // Do not change the enumeration values or you will break third-party 67 // installers. 68 enum { 69 PROCESS_END_NORMAL_TERMINATON = 0, 70 PROCESS_END_KILLED_BY_USER = 1, 71 PROCESS_END_PROCESS_WAS_HUNG = 2 72 }; 73 74 // Returns the id of the current process. 75 ProcessId GetCurrentProcId(); 76 77 // Returns the ProcessHandle of the current process. 78 ProcessHandle GetCurrentProcessHandle(); 79 80 // Converts a PID to a process handle. This handle must be closed by 81 // CloseProcessHandle when you are done with it. Returns true on success. 82 bool OpenProcessHandle(ProcessId pid, ProcessHandle* handle); 83 84 // Converts a PID to a process handle. On Windows the handle is opened 85 // with more access rights and must only be used by trusted code. 86 // You have to close returned handle using CloseProcessHandle. Returns true 87 // on success. 88 bool OpenPrivilegedProcessHandle(ProcessId pid, ProcessHandle* handle); 89 90 // Closes the process handle opened by OpenProcessHandle. 91 void CloseProcessHandle(ProcessHandle process); 92 93 // Returns the unique ID for the specified process. This is functionally the 94 // same as Windows' GetProcessId(), but works on versions of Windows before 95 // Win XP SP1 as well. 96 ProcessId GetProcId(ProcessHandle process); 97 98 #if defined(XP_UNIX) 99 // Close all file descriptors, except for std{in,out,err} and those 100 // for which the given function returns true. Only call this function 101 // in a child process where you know that there aren't any other 102 // threads. 103 void CloseSuperfluousFds(void* aCtx, bool (*aShouldPreserve)(void*, int)); 104 105 typedef std::vector<std::pair<int, int> > file_handle_mapping_vector; 106 typedef std::map<std::string, std::string> environment_map; 107 108 // Deleter for the array of strings allocated within BuildEnvironmentArray. 109 struct FreeEnvVarsArray { 110 void operator()(char** array); 111 }; 112 113 typedef mozilla::UniquePtr<char*[], FreeEnvVarsArray> EnvironmentArray; 114 #endif 115 116 struct LaunchOptions { 117 // If true, wait for the process to terminate. Otherwise, return 118 // immediately. 119 bool wait = false; 120 121 #if defined(XP_WIN) 122 bool start_hidden = false; 123 124 // Start as an independent process rather than a process that is closed by the 125 // parent job. This will pass the flag CREATE_BREAKAWAY_FROM_JOB. 126 bool start_independent = false; 127 128 // Environment variables to be applied in addition to the current 129 // process's environment, replacing them where necessary. 130 EnvironmentMap env_map; 131 132 std::vector<HANDLE> handles_to_inherit; 133 #endif 134 #if defined(XP_UNIX) 135 environment_map env_map; 136 137 // If non-null, specifies the entire environment to use for the 138 // child process, instead of inheriting from the parent; env_map is 139 // ignored in that case. Note that the strings are allocated using 140 // malloc (e.g., with strdup), but the array of pointers is 141 // allocated with new[] and is terminated with a null pointer. 142 EnvironmentArray full_env; 143 144 // If non-empty, set the child process's current working directory. 145 std::string workdir; 146 147 // A mapping of (src fd -> dest fd) to propagate into the child 148 // process. All other fds will be closed, except std{in,out,err}. 149 file_handle_mapping_vector fds_to_remap; 150 #endif 151 152 #if defined(XP_LINUX) && defined(MOZ_SANDBOX) 153 // These fields are used by the sandboxing code in SandboxLaunch.cpp. 154 // It's not ideal to have them here, but trying to abstract them makes 155 // it harder to serialize LaunchOptions for the fork server. 156 // 157 // (fork_flags holds extra flags for the clone() syscall, and 158 // sandbox_chroot_server, if set, is used internally by the sandbox 159 // to chroot() the process to an empty directory.) 160 int fork_flags = 0; 161 mozilla::UniqueFileHandle sandbox_chroot_server; 162 #endif 163 164 #ifdef XP_DARWIN 165 // On macOS 10.14+, disclaims responsibility for the child process 166 // with respect to privacy/security permission prompts and 167 // decisions. Ignored if not supported by the OS. 168 bool disclaim = false; 169 # ifdef __aarch64__ 170 // The architecture to launch when launching a "universal" binary. 171 // Note: the implementation only supports launching x64 child 172 // processes from arm64 parent processes. 173 uint32_t arch = PROCESS_ARCH_INVALID; 174 # endif // __aarch64__ 175 #endif // XP_DARWIN 176 }; 177 178 #if defined(XP_WIN) 179 // Runs the given application name with the given command line. Normally, the 180 // first command line argument should be the path to the process, and don't 181 // forget to quote it. 182 // 183 // Example (including literal quotes) 184 // cmdline = "c:\windows\explorer.exe" -foo "c:\bar\" 185 // 186 // If process_handle is non-NULL, the process handle of the launched app will be 187 // stored there on a successful launch. 188 // NOTE: In this case, the caller is responsible for closing the handle so 189 // that it doesn't leak! 190 Result<Ok, LaunchError> LaunchApp(const std::wstring& cmdline, 191 const LaunchOptions& options, 192 ProcessHandle* process_handle); 193 194 Result<Ok, LaunchError> LaunchApp(const CommandLine& cl, const LaunchOptions&, 195 ProcessHandle* process_handle); 196 #else 197 // Runs the application specified in argv[0] with the command line argv. 198 // 199 // The pid will be stored in process_handle if that pointer is 200 // non-null. 201 // 202 // Note that the first argument in argv must point to the filename, 203 // and must be fully specified (i.e., this will not search $PATH). 204 Result<Ok, LaunchError> LaunchApp(const std::vector<std::string>& argv, 205 LaunchOptions&& options, 206 ProcessHandle* process_handle); 207 208 // Merge an environment map with the current environment. 209 // Existing variables are overwritten by env_vars_to_set. 210 EnvironmentArray BuildEnvironmentArray(const environment_map& env_vars_to_set); 211 #endif 212 213 // Attempts to kill the process identified by the given process 214 // entry structure, giving it the specified exit code. 215 // Returns true if this is successful, false otherwise. 216 bool KillProcess(ProcessHandle process, int exit_code); 217 218 #ifdef XP_UNIX 219 enum class BlockingWait { No, Yes }; 220 enum class ProcessStatus { Running, Exited, Killed, Error }; 221 222 // Checks whether the given process has exited; returns a 223 // `ProcessStatus` indicating whether the process is still running, 224 // exited normally, was killed by a signal, or whether an error was 225 // encountered (e.g., if the given process isn't a direct child of 226 // this process). In the `Exited` and `Killed` cases, the dead 227 // process is collected (like `waitpid`) and the pid is freed for 228 // potential reuse by another process. 229 // 230 // The value returned in `*info_out` depends on the process status: 231 // * for `Running`, it's always set to 0 232 // * for `Exited`, the value passed to `exit()` 233 // * for `Killed`, the signal number 234 // * for `Error`, the error code (like `errno`) 235 // 236 // If the `blocking` parameter is set to `Yes`, this function will try 237 // to block the calling thread indefinitely until the process exits. 238 // This may not be possible (if the child is also being debugged by 239 // the parent process, e.g. due to the crash reporter), in which case 240 // it will return `Running` and the caller will need to wait and retry. 241 ProcessStatus WaitForProcess(ProcessHandle handle, BlockingWait blocking, 242 int* info_out); 243 #endif 244 245 } // namespace base 246 247 namespace mozilla { 248 249 class EnvironmentLog { 250 public: 251 template <size_t N> 252 explicit EnvironmentLog(const char (&varname)[N]) 253 : EnvironmentLog(varname, N) {} 254 255 ~EnvironmentLog() {} 256 257 void print(const char* format, ...); 258 259 private: 260 explicit EnvironmentLog(const char* varname, size_t len); 261 262 #if defined(XP_WIN) 263 std::wstring fname_; 264 #else 265 std::string fname_; 266 #endif 267 268 DISALLOW_EVIL_CONSTRUCTORS(EnvironmentLog); 269 }; 270 271 } // namespace mozilla 272 273 #if defined(XP_WIN) 274 // Undo the windows.h damage 275 # undef GetMessage 276 # undef CreateEvent 277 # undef GetClassName 278 # undef GetBinaryType 279 # undef RemoveDirectory 280 # undef LoadImage 281 # undef LoadIcon 282 #endif 283 284 #endif // BASE_PROCESS_UTIL_H_