Line data Source code
1 : // Copyright (c) 2013-2022 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/eventdispatcher
4 : // contact@m2osw.com
5 : //
6 : // This program is free software; you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation; either version 2 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License along
17 : // with this program; if not, write to the Free Software Foundation, Inc.,
18 : // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 :
20 : /** \file
21 : * \brief Implementation of the process_list loader.
22 : *
23 : * This object loads the complete list of process identifiers (pid_t)
24 : * found under /proc. You can further query about many of the parameters
25 : * of a process using the resulting process_info objects.
26 : *
27 : * If interested by a specific process for which you know the pid, you can
28 : * instead use a process_info object directly.
29 : */
30 :
31 : // self
32 : //
33 : #include <cppprocess/process_list.h>
34 :
35 :
36 : // snapdev lib
37 : //
38 : #include <snapdev/glob_to_list.h>
39 : #include <snapdev/map_keyset.h>
40 :
41 :
42 : // snaplogger lib
43 : //
44 : #include <snaplogger/message.h>
45 :
46 :
47 : // C++ lib
48 : //
49 : #include <list>
50 :
51 :
52 : // C lib
53 : //
54 : //#include <proc/readproc.h>
55 : //#include <stdio.h>
56 : //#include <sys/prctl.h>
57 : //#include <sys/wait.h>
58 : //#include <unistd.h>
59 :
60 :
61 : // last include
62 : //
63 : #include <snapdev/poison.h>
64 :
65 :
66 :
67 : namespace cppprocess
68 : {
69 :
70 :
71 :
72 : /** \brief The process list constructor determines the list of processes.
73 : *
74 : * The constructor builds the list of existing processes from /proc with
75 : * all the file names that are only digits. Those are the process PIDs.
76 : * The resulting list is saved in the process_list as proc_info objects
77 : * which can be quiered for additional information.
78 : *
79 : * The additional information is loaded at the time it gets queried which
80 : * means you may actually get an invalid result (i.e. if the process
81 : * died before you were able to query its data).
82 : *
83 : * You can refresh the list of processes by calling the refresh() function.
84 : * It will re-read the list of available processes by reading their pid
85 : * from the `/proc/...` folder.
86 : */
87 0 : process_list::process_list()
88 : {
89 0 : refresh();
90 0 : }
91 :
92 :
93 : /** \brief Refresh the list of processes.
94 : *
95 : * If you want to keep a process_list object around for a while, it is
96 : * going to decay over time (i.e. many processes die and new onces get
97 : * created).
98 : *
99 : * This function refreshes the list of process_info objects defined in
100 : * this process_list.
101 : */
102 0 : void process_list::refresh()
103 : {
104 : // Keep a copy of the existing keys; if still in that set at the end
105 : // of the following loop, delete those from the map
106 : //
107 0 : std::set<pid_t> keys;
108 0 : snapdev::map_keyset(keys, *this);
109 :
110 : // gather current set of processes (pid_t)
111 : //
112 : typedef std::list<std::string> list_t;
113 0 : snapdev::glob_to_list<list_t> filenames;
114 : filenames.read_path<
115 : snapdev::glob_to_list_flag_t::GLOB_FLAG_IGNORE_ERRORS
116 0 : , snapdev::glob_to_list_flag_t::GLOB_FLAG_ONLY_DIRECTORIES>("/proc/[0-9]*");
117 :
118 0 : for(auto f : filenames)
119 : {
120 0 : if(f.length() < 7) // strlen("/proc/[0-9]") == 7
121 : {
122 0 : continue;
123 : }
124 :
125 : // convert string to integer
126 : //
127 0 : pid_t pid(0);
128 0 : char const * s(f.c_str() + 6);
129 0 : for(; *s >= '0' && *s <= '9'; ++s)
130 : {
131 0 : pid *= 10;
132 0 : pid += *s - '0';
133 : }
134 0 : if(*s != '\0'
135 0 : || pid == 0)
136 : {
137 : // invalid character or number ("0" is not valid)
138 : //
139 0 : continue;
140 : }
141 :
142 : // got a pid considered valid, use it
143 : //
144 0 : keys.erase(pid);
145 0 : auto it(map::find(pid));
146 0 : if(it == end())
147 : {
148 0 : insert({pid, std::make_shared<process_info>(pid)});
149 : }
150 : }
151 :
152 : // delete processes from our list if they died
153 : //
154 0 : for(auto k : keys)
155 : {
156 0 : auto it(map::find(k));
157 0 : if(it != end())
158 : {
159 0 : erase(it);
160 : }
161 : }
162 0 : }
163 :
164 :
165 : /** \brief Find a process_info object by pid.
166 : *
167 : * This function returns the process info object searching by its process
168 : * identifier.
169 : *
170 : * \return A pointer to the process_info or null.
171 : */
172 0 : process_info::pointer_t process_list::find(pid_t pid)
173 : {
174 0 : auto it(map::find(pid));
175 0 : if(it == end())
176 : {
177 0 : return process_info::pointer_t();
178 : }
179 :
180 0 : return it->second;
181 : }
182 :
183 :
184 : /** \brief Find a process_info object by its process basename.
185 : *
186 : * This function goes through the map of processes and returns the
187 : * first one which name matches the specified \p basename.
188 : *
189 : * \return A pointer to a process_info or null.
190 : */
191 0 : process_info::pointer_t process_list::find(std::string const & basename)
192 : {
193 0 : for(auto & p : *this)
194 : {
195 0 : if(p.second->get_basename() == basename)
196 : {
197 0 : return p.second;
198 : }
199 : }
200 :
201 0 : return process_info::pointer_t();
202 : }
203 :
204 :
205 6 : } // namespace cppprocess
206 : // vim: ts=4 sw=4 et
|