1 // Copyright 2013 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // This file contains methods to iterate over processes on the system. 6 7 #ifndef BASE_PROCESS_PROCESS_ITERATOR_H_ 8 #define BASE_PROCESS_PROCESS_ITERATOR_H_ 9 10 #include <stddef.h> 11 12 #include <list> 13 #include <string> 14 #include <vector> 15 16 #include "base/base_export.h" 17 #include "base/compiler_specific.h" 18 #include "base/files/file_path.h" 19 #include "base/memory/raw_ptr.h" 20 #include "base/process/process.h" 21 #include "base/strings/string_util.h" 22 #include "build/build_config.h" 23 24 #if BUILDFLAG(IS_WIN) 25 #include <windows.h> 26 27 #include <tlhelp32.h> 28 #elif BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_OPENBSD) 29 #include <sys/sysctl.h> 30 #elif BUILDFLAG(IS_FREEBSD) 31 #include <sys/user.h> 32 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) 33 #include <dirent.h> 34 #endif 35 36 namespace base { 37 38 #if BUILDFLAG(IS_WIN) 39 struct ProcessEntry : public PROCESSENTRY32 { pidProcessEntry40 ProcessId pid() const { return th32ProcessID; } parent_pidProcessEntry41 ProcessId parent_pid() const { return th32ParentProcessID; } exe_fileProcessEntry42 const wchar_t* exe_file() const { return szExeFile; } 43 }; 44 #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) 45 struct BASE_EXPORT ProcessEntry { 46 ProcessEntry(); 47 ProcessEntry(const ProcessEntry& other); 48 ~ProcessEntry(); 49 50 ProcessId pid() const { return pid_; } 51 ProcessId parent_pid() const { return ppid_; } 52 ProcessId gid() const { return gid_; } 53 const char* exe_file() const { return exe_file_.c_str(); } 54 const std::vector<std::string>& cmd_line_args() const LIFETIME_BOUND { 55 return cmd_line_args_; 56 } 57 58 ProcessId pid_; 59 ProcessId ppid_; 60 ProcessId gid_; 61 std::string exe_file_; 62 std::vector<std::string> cmd_line_args_; 63 }; 64 #endif // BUILDFLAG(IS_WIN) 65 66 // Used to filter processes by process ID. 67 class ProcessFilter { 68 public: 69 // Returns true to indicate set-inclusion and false otherwise. This method 70 // should not have side-effects and should be idempotent. 71 virtual bool Includes(const ProcessEntry& entry) const = 0; 72 73 protected: 74 virtual ~ProcessFilter() = default; 75 }; 76 77 // This class provides a way to iterate through a list of processes on the 78 // current machine with a specified filter. 79 // To use, create an instance and then call NextProcessEntry() until it returns 80 // false. 81 class BASE_EXPORT ProcessIterator { 82 public: 83 typedef std::list<ProcessEntry> ProcessEntries; 84 85 explicit ProcessIterator(const ProcessFilter* filter); 86 87 ProcessIterator(const ProcessIterator&) = delete; 88 ProcessIterator& operator=(const ProcessIterator&) = delete; 89 90 virtual ~ProcessIterator(); 91 92 // If there's another process that matches the given executable name, 93 // returns a const pointer to the corresponding PROCESSENTRY32. 94 // If there are no more matching processes, returns NULL. 95 // The returned pointer will remain valid until NextProcessEntry() 96 // is called again or this NamedProcessIterator goes out of scope. 97 const ProcessEntry* NextProcessEntry(); 98 99 // Takes a snapshot of all the ProcessEntry found. 100 ProcessEntries Snapshot(); 101 102 protected: 103 virtual bool IncludeEntry(); entry()104 const ProcessEntry& entry() const LIFETIME_BOUND { return entry_; } 105 106 private: 107 // Determines whether there's another process (regardless of executable) 108 // left in the list of all processes. Returns true and sets entry_ to 109 // that process's info if there is one, false otherwise. 110 bool CheckForNextProcess(); 111 112 // Initializes a PROCESSENTRY32 data structure so that it's ready for 113 // use with Process32First/Process32Next. 114 void InitProcessEntry(ProcessEntry* entry); 115 116 #if BUILDFLAG(IS_WIN) 117 HANDLE snapshot_; 118 bool started_iteration_ = false; 119 #elif BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_BSD) 120 std::vector<kinfo_proc> kinfo_procs_; 121 size_t index_of_kinfo_proc_ = 0; 122 #elif BUILDFLAG(IS_POSIX) 123 struct DIRClose { operatorDIRClose124 inline void operator()(DIR* x) const { 125 if (x) 126 closedir(x); 127 } 128 }; 129 std::unique_ptr<DIR, DIRClose> procfs_dir_; 130 #endif 131 ProcessEntry entry_; 132 raw_ptr<const ProcessFilter> filter_; 133 }; 134 135 // This class provides a way to iterate through the list of processes 136 // on the current machine that were started from the given executable 137 // name. To use, create an instance and then call NextProcessEntry() 138 // until it returns false. 139 // If `use_prefix_match` is true, this iterates all processes that 140 // begin with `executable_name`; for example, "Google Chrome Helper" would 141 // match "Google Chrome Helper", "Google Chrome Helper (Renderer)" and 142 // "Google Chrome Helper (GPU)" if `use_prefix_match` is true and otherwise 143 // only "Google Chrome Helper". This option is only implemented on Mac. 144 class BASE_EXPORT NamedProcessIterator : public ProcessIterator { 145 public: 146 NamedProcessIterator(const FilePath::StringType& executable_name, 147 const ProcessFilter* filter, 148 bool use_prefix_match = false); 149 150 NamedProcessIterator(const NamedProcessIterator&) = delete; 151 NamedProcessIterator& operator=(const NamedProcessIterator&) = delete; 152 153 ~NamedProcessIterator() override; 154 155 protected: 156 bool IncludeEntry() override; 157 158 private: 159 FilePath::StringType executable_name_; 160 const bool use_prefix_match_; 161 }; 162 163 // Returns the number of processes on the machine that are running from the 164 // given executable name. If filter is non-null, then only processes selected 165 // by the filter will be counted. 166 BASE_EXPORT int GetProcessCount(const FilePath::StringType& executable_name, 167 const ProcessFilter* filter); 168 169 } // namespace base 170 171 #endif // BASE_PROCESS_PROCESS_ITERATOR_H_ 172