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