1 /*
2 * Process.cpp
3 *
4 * Copyright (C) 2012 Evidence Srl - www.evidence.eu.com
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library 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 GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <stdexcept>
22 #include <sched.h>
23 #include <sys/wait.h>
24 #include <strings.h>
25 #include <signal.h>
26
27 #include <iostream>
28
31
32 namespace onposix {
33
34 /**
35 * \brief Create a process
36 *
37 * This function creates a new process through fork().
38 * This function is not meant to be called explicitly,
39 * but it is automatically called by the constructors.
40 * @exception std::runtime_error in case the process cannot
41 * be created.
42 */
44 {
48 ERROR(
"Cannot start process");
49 throw std::runtime_error ("Async error");
50 }
51
53 // Child
56 } else {
57 // Parent
59 }
61 }
62
63 /**
64 * \brief Constructor to run a specific function
65 *
66 * This constructor creates a new process that will run the
67 * function given as argument.
68 * @param function: pointer to the function that must be run
69 */
71 is_child_(false),
72 running_(false),
73 status_(0)
74 {
77 (*function)();
78 }
79 }
80
81 /**
82 * \brief Constructor to run a specific program
83 *
84 * This constructor creates a new process that will run the
85 * program given as argument. This contructor invokes fork()+execvp().
86 * @param program: name of the program to be run
87 * @args args: list of arguments
88 */
90 const std::vector<std::string>& args):
91 is_child_(false),
92 running_(false),
93 status_(0)
94 {
97 char* c_args [20];
98 c_args[0] = const_cast<char*> (program.c_str());
99 for (unsigned int i = 0; i < args.size(); ++i){
100 c_args[i+1] = const_cast<char*> (args[i].c_str());
101 }
102 c_args[args.size()+1] = (char*) NULL;
103
104 execvp(program.c_str(), c_args);
105 }
106 }
107
108 /**
109 * \brief Function to wait the termination of the process
110 *
111 * To avoid deadlocks, this function can be called only by the parent
112 * and not by the child itself.
113 * @return false in case the function is called by the child or in
114 * case of abnormal termination; true in case of normal termination
115 */
117 {
119 return false;
123 return true;
124 else
125 return false;
126 }
127
128 /**
129 * \brief Function to check if the child has terminated correctly
130 *
131 * This function must be invoked after waitForTermination() and
132 * allows to inspect the termination status of the child.
133 * @return true in case of normal termination; false otherwise
134 */
136 {
138 return false;
140 return true;
141 else
142 return false;
143 }
144
145 /**
146 * \brief Function to check if the child has terminated for a signal
147 *
148 * This function must be invoked after waitForTermination() and
149 * allows to inspect the termination status of the child.
150 * @return true in case the child has terminated due to a signal;
151 * false otherwise
152 */
154 {
156 return false;
158 return true;
159 else
160 return false;
161 }
162
163
164
165 /**
166 * \brief Function to send a signal to the process
167 *
168 * This method allows to send a signal to the process related to
169 * this instance of Process. This function wraps the classical kill()
170 * function.
171 * The list of signals is available on /usr/include/bits/signum.h
172 * @param sig the signal to be sent
173 * @return true on success; false if some error occurred
174 */
176 {
177 if (kill(
pid_, sig) != 0){
178 ERROR(
"Can't send signal " << sig);
179 return false;
180 }
181 return true;
182 }
183
184 /**
185 * \brief Set a handler for a specific signal
186 *
187 * This method allows to manually set a handler for handling a specific signal.
188 * The list of signals is available on /usr/include/bits/signum.h
189 * Use signals less as possible, mainly for standard situations.
190 * During the execution of the handler other signals may arrive. This can lead
191 * to inconsistent states. The handler must be short.
192 * It must just update the internal state and/or kill the application.
193 * Not all library functions can be called inside the handler without having
194 * strange behaviors (see man signal). In particular, it's not safe calling
195 * functions of the standard library, like printf() or exit(), or other
196 * functions defined inside the application itself. The access to global
197 * variables is not safe either, unless they have been defined as volatile.
198 * @param sig the signal to be sent
199 * @return true on success; false if some error occurred
200 */
202 {
203 bool ret = true;
204 sigset_t oldset, set;
205 struct sigaction sa;
206 /* mask all signals until the handlers are installed */
207 sigfillset(&set);
208 sigprocmask(SIG_SETMASK, &set, &oldset);
209 bzero( &sa, sizeof(sa) );
210 sa.sa_handler = handler;
211 if (sigaction(sig, &sa, NULL) < 0) {
212 ERROR(
"Can't set signal " << sig);
213 ret = false;
214 }
215 /* remove the mask */
216 sigprocmask(SIG_SETMASK, &oldset,NULL);
217 return ret;
218 }
219
220
221
222 /**
223 * \brief Set scheduling policy and priority
224 *
225 * @param policy: policy (SCHED_FIFO, SCHED_RR or SCHED_OTHER)
226 * @param priority: scheduling priority
227 * @return true in case of success; false in case of error
228 */
230 {
231 struct sched_param p;
232 p.sched_priority = priority;
233 if (sched_setscheduler(
pid_, policy, &p) == 0)
234 return true;
235 else
236 return false;
237 }
238
239
240
241 /**
242 * \brief Get current scheduling policy and priority
243 *
244 * @param policy: policy (SCHED_FIFO, SCHED_RR or SCHED_OTHER)
245 * @param priority: scheduling priority; it has a meaning only for SCHED_FIFO
246 * and SCHED_RR
247 * @return true in case of success; false in case of error
248 */
250 {
251 struct sched_param p;
252 int ret = sched_getparam(
pid_, &p);
253 *priority = p.sched_priority;
254 *policy = sched_getscheduler(
pid_);
255 if ((*policy < 0) || (ret < 0))
256 return false;
257 else
258 return true;
259 }
260
261
262 #if defined(ONPOSIX_LINUX_SPECIFIC) && defined(__GLIBC__) && \
263 ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ > 3)))
264 /**
265 * \brief Set CPU affinity
266 *
267 * Example of usage:
268 * \code
269 * std::vector<bool> v (2);
270 * v[0] = true;
271 * v[1] = false;
272 * setAffinity(v);
273 * \endcode
274 * @param v: vector of booleans containing the affinity (true/false)
275 * @exception std::runtime_error in case affinity cannot be set
276 */
277 void Process::setAffinity(const std::vector<bool>& v)
278 {
279 cpu_set_t s;
280 CPU_ZERO(&s);
281 for (unsigned int i = 0; (i < v.size()) && (i < CPU_SETSIZE); ++i)
282 if (v[i])
283 CPU_SET(i, &s);
284
285 if ((sched_setaffinity(
pid_,
sizeof(s), &s) != 0))
286 throw std::runtime_error ("Set affinity error");
287 }
288
289 /**
290 * \brief Get CPU affinity
291 *
292 * Example of usage:
293 * \code
294 * std::vector<bool> v (2);
295 * getAffinity(&v);
296 * std::cout << "Affinity: " << v[0] << " " << v[1] << std::endl;
297 * \endcode
298 * @param v: vector of booleans containing the current affinity (true/false)
299 * @exception std::runtime_error in case affinity cannot be get
300 */
301 void Process::getAffinity(std::vector<bool>* v)
302 {
303 cpu_set_t s;
304 CPU_ZERO(&s);
305
306 if ((sched_getaffinity(
pid_,
sizeof(s), &s) != 0))
307 throw std::runtime_error ("Get affinity error");
308
309 for (unsigned int j = 0; (j < CPU_SETSIZE) && (j < v->size()); ++j) {
310 if (CPU_ISSET(j, &s))
311 (*v)[j] = true;
312 else
313 (*v)[j] = false;
314 }
315 }
316 #endif /* ONPOSIX_LINUX_SPECIFIC && GLIBC */
317
318
319 } /* onposix */