| Avi Drissman | e4622aa | 2022-09-08 20:36:06 | [diff] [blame] | 1 | // Copyright 2013 The Chromium Authors |
| [email protected] | d3acb67 | 2013-05-31 15:38:01 | [diff] [blame] | 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 | |
| avi | beced7c | 2015-12-24 06:47:59 | [diff] [blame] | 10 | #include <stddef.h> |
| 11 | |
| [email protected] | d3acb67 | 2013-05-31 15:38:01 | [diff] [blame] | 12 | #include <list> |
| 13 | #include <string> |
| 14 | #include <vector> |
| 15 | |
| [email protected] | d3acb67 | 2013-05-31 15:38:01 | [diff] [blame] | 16 | #include "base/base_export.h" |
| Tom Sepez | 04e98bf | 2024-10-25 18:19:31 | [diff] [blame] | 17 | #include "base/compiler_specific.h" |
| [email protected] | d3acb67 | 2013-05-31 15:38:01 | [diff] [blame] | 18 | #include "base/files/file_path.h" |
| Keishi Hattori | 0e45c02 | 2021-11-27 09:25:52 | [diff] [blame] | 19 | #include "base/memory/raw_ptr.h" |
| [email protected] | dd4b5126 | 2013-07-25 21:38:23 | [diff] [blame] | 20 | #include "base/process/process.h" |
| jdoerrie | 79b354c | 2019-05-07 16:41:07 | [diff] [blame] | 21 | #include "base/strings/string_util.h" |
| [email protected] | dd4b5126 | 2013-07-25 21:38:23 | [diff] [blame] | 22 | #include "build/build_config.h" |
| [email protected] | d3acb67 | 2013-05-31 15:38:01 | [diff] [blame] | 23 | |
| Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 24 | #if BUILDFLAG(IS_WIN) |
| [email protected] | d3acb67 | 2013-05-31 15:38:01 | [diff] [blame] | 25 | #include <windows.h> |
| Bruce Dawson | a1e1cfcb | 2022-11-22 20:04:35 | [diff] [blame] | 26 | |
| [email protected] | d3acb67 | 2013-05-31 15:38:01 | [diff] [blame] | 27 | #include <tlhelp32.h> |
| Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 28 | #elif BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_OPENBSD) |
| [email protected] | d3acb67 | 2013-05-31 15:38:01 | [diff] [blame] | 29 | #include <sys/sysctl.h> |
| Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 30 | #elif BUILDFLAG(IS_FREEBSD) |
| [email protected] | fd0acad | 2014-03-11 04:11:02 | [diff] [blame] | 31 | #include <sys/user.h> |
| Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 32 | #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) |
| [email protected] | d3acb67 | 2013-05-31 15:38:01 | [diff] [blame] | 33 | #include <dirent.h> |
| 34 | #endif |
| 35 | |
| 36 | namespace base { |
| 37 | |
| Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 38 | #if BUILDFLAG(IS_WIN) |
| [email protected] | d3acb67 | 2013-05-31 15:38:01 | [diff] [blame] | 39 | struct ProcessEntry : public PROCESSENTRY32 { |
| 40 | ProcessId pid() const { return th32ProcessID; } |
| 41 | ProcessId parent_pid() const { return th32ParentProcessID; } |
| Jan Wilken Dörrie | b630aca | 2019-12-04 10:59:11 | [diff] [blame] | 42 | const wchar_t* exe_file() const { return szExeFile; } |
| [email protected] | d3acb67 | 2013-05-31 15:38:01 | [diff] [blame] | 43 | }; |
| Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 44 | #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA) |
| [email protected] | d3acb67 | 2013-05-31 15:38:01 | [diff] [blame] | 45 | struct BASE_EXPORT ProcessEntry { |
| 46 | ProcessEntry(); |
| vmpstr | 7c787706 | 2016-02-18 22:12:24 | [diff] [blame] | 47 | ProcessEntry(const ProcessEntry& other); |
| [email protected] | d3acb67 | 2013-05-31 15:38:01 | [diff] [blame] | 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(); } |
| Tom Sepez | 04e98bf | 2024-10-25 18:19:31 | [diff] [blame] | 54 | const std::vector<std::string>& cmd_line_args() const LIFETIME_BOUND { |
| [email protected] | d3acb67 | 2013-05-31 15:38:01 | [diff] [blame] | 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 | }; |
| Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 64 | #endif // BUILDFLAG(IS_WIN) |
| [email protected] | d3acb67 | 2013-05-31 15:38:01 | [diff] [blame] | 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: |
| Chris Watkins | 091d629 | 2017-12-13 04:25:58 | [diff] [blame] | 74 | virtual ~ProcessFilter() = default; |
| [email protected] | d3acb67 | 2013-05-31 15:38:01 | [diff] [blame] | 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); |
| Peter Boström | 7319bbd | 2021-09-15 22:59:38 | [diff] [blame] | 86 | |
| 87 | ProcessIterator(const ProcessIterator&) = delete; |
| 88 | ProcessIterator& operator=(const ProcessIterator&) = delete; |
| 89 | |
| [email protected] | d3acb67 | 2013-05-31 15:38:01 | [diff] [blame] | 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(); |
| Tom Sepez | 04e98bf | 2024-10-25 18:19:31 | [diff] [blame] | 104 | const ProcessEntry& entry() const LIFETIME_BOUND { return entry_; } |
| [email protected] | d3acb67 | 2013-05-31 15:38:01 | [diff] [blame] | 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 | |
| Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 116 | #if BUILDFLAG(IS_WIN) |
| [email protected] | d3acb67 | 2013-05-31 15:38:01 | [diff] [blame] | 117 | HANDLE snapshot_; |
| Lei Zhang | 6f418e0 | 2023-02-08 21:55:43 | [diff] [blame] | 118 | bool started_iteration_ = false; |
| Xiaohan Wang | 37e8161 | 2022-01-15 18:27:00 | [diff] [blame] | 119 | #elif BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_BSD) |
| [email protected] | d3acb67 | 2013-05-31 15:38:01 | [diff] [blame] | 120 | std::vector<kinfo_proc> kinfo_procs_; |
| Lei Zhang | 6f418e0 | 2023-02-08 21:55:43 | [diff] [blame] | 121 | size_t index_of_kinfo_proc_ = 0; |
| Ali Hijazi | e8035ce4 | 2022-07-29 15:02:46 | [diff] [blame] | 122 | #elif BUILDFLAG(IS_POSIX) |
| 123 | struct DIRClose { |
| 124 | inline void operator()(DIR* x) const { |
| Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 125 | if (x) { |
| Ali Hijazi | e8035ce4 | 2022-07-29 15:02:46 | [diff] [blame] | 126 | closedir(x); |
| Peter Kasting | 134ef9af | 2024-12-28 02:30:09 | [diff] [blame] | 127 | } |
| Ali Hijazi | e8035ce4 | 2022-07-29 15:02:46 | [diff] [blame] | 128 | } |
| 129 | }; |
| 130 | std::unique_ptr<DIR, DIRClose> procfs_dir_; |
| [email protected] | d3acb67 | 2013-05-31 15:38:01 | [diff] [blame] | 131 | #endif |
| 132 | ProcessEntry entry_; |
| Keishi Hattori | 0e45c02 | 2021-11-27 09:25:52 | [diff] [blame] | 133 | raw_ptr<const ProcessFilter> filter_; |
| [email protected] | d3acb67 | 2013-05-31 15:38:01 | [diff] [blame] | 134 | }; |
| 135 | |
| 136 | // This class provides a way to iterate through the list of processes |
| 137 | // on the current machine that were started from the given executable |
| 138 | // name. To use, create an instance and then call NextProcessEntry() |
| 139 | // until it returns false. |
| Leonard Grey | 77c540e | 2022-10-28 20:04:15 | [diff] [blame] | 140 | // If `use_prefix_match` is true, this iterates all processes that |
| 141 | // begin with `executable_name`; for example, "Google Chrome Helper" would |
| 142 | // match "Google Chrome Helper", "Google Chrome Helper (Renderer)" and |
| 143 | // "Google Chrome Helper (GPU)" if `use_prefix_match` is true and otherwise |
| 144 | // only "Google Chrome Helper". This option is only implemented on Mac. |
| [email protected] | d3acb67 | 2013-05-31 15:38:01 | [diff] [blame] | 145 | class BASE_EXPORT NamedProcessIterator : public ProcessIterator { |
| 146 | public: |
| 147 | NamedProcessIterator(const FilePath::StringType& executable_name, |
| Leonard Grey | 77c540e | 2022-10-28 20:04:15 | [diff] [blame] | 148 | const ProcessFilter* filter, |
| 149 | bool use_prefix_match = false); |
| Peter Boström | 7319bbd | 2021-09-15 22:59:38 | [diff] [blame] | 150 | |
| 151 | NamedProcessIterator(const NamedProcessIterator&) = delete; |
| 152 | NamedProcessIterator& operator=(const NamedProcessIterator&) = delete; |
| 153 | |
| dcheng | 5648818 | 2014-10-21 10:54:51 | [diff] [blame] | 154 | ~NamedProcessIterator() override; |
| [email protected] | d3acb67 | 2013-05-31 15:38:01 | [diff] [blame] | 155 | |
| 156 | protected: |
| dcheng | 5648818 | 2014-10-21 10:54:51 | [diff] [blame] | 157 | bool IncludeEntry() override; |
| [email protected] | d3acb67 | 2013-05-31 15:38:01 | [diff] [blame] | 158 | |
| 159 | private: |
| 160 | FilePath::StringType executable_name_; |
| Leonard Grey | 77c540e | 2022-10-28 20:04:15 | [diff] [blame] | 161 | const bool use_prefix_match_; |
| [email protected] | d3acb67 | 2013-05-31 15:38:01 | [diff] [blame] | 162 | }; |
| 163 | |
| 164 | // Returns the number of processes on the machine that are running from the |
| 165 | // given executable name. If filter is non-null, then only processes selected |
| 166 | // by the filter will be counted. |
| 167 | BASE_EXPORT int GetProcessCount(const FilePath::StringType& executable_name, |
| 168 | const ProcessFilter* filter); |
| 169 | |
| 170 | } // namespace base |
| 171 | |
| 172 | #endif // BASE_PROCESS_PROCESS_ITERATOR_H_ |