Line data Source code
1 : // DUNE DAQ modification notice:
2 : // This file has been modified from the original ATLAS system source for the DUNE DAQ project.
3 : // Fork baseline commit: system-00-00-20 (2020-09-25).
4 : // Renamed since fork: yes (from src/Executable.cxx to src/Executable.cpp).
5 :
6 : /*
7 : * Executable.cxx
8 : * ers
9 : *
10 : * Created by Matthias Wiesmann on 06.01.05.
11 : * Copyright 2005 CERN. All rights reserved.
12 : *
13 : */
14 :
15 : #include <cstdio>
16 : #include <cstdlib>
17 : #include <fcntl.h>
18 : #include <iostream>
19 : #include <pthread.h>
20 : #include <signal.h>
21 : #include <sstream>
22 : #include <sys/stat.h>
23 : #include <sys/types.h>
24 : #include <sys/uio.h>
25 : #include <unistd.h>
26 :
27 : #include "ers/Assertion.hpp"
28 : #include "ers/ers.hpp"
29 :
30 : #include "okssystem/Descriptor.hpp"
31 : #include "okssystem/Environment.hpp"
32 : #include "okssystem/Executable.hpp"
33 : #include "okssystem/Process.hpp"
34 : #include "okssystem/exceptions.hpp"
35 :
36 : const char* const OksSystem::Executable::SHELL_COMMAND = "/bin/sh";
37 : const char* const OksSystem::Executable::SHELL_COMMAND_PARAM = "-c";
38 :
39 : /** This method is a safe replacement for the okssystem function.
40 : * It basically offers the same functionality with better error handling.
41 : * The command is executed in a shell via \c /bin/sh \c -c.
42 : * If the command is successfull (return value 0), this method returns the resulting string.
43 : * If the command fails, this method throws an exception of type \c okssystem::ExecutionIssue.
44 : * This exception contains the return code and the content of stderr.
45 : * \param command the command to execute
46 : * \return the content of the stdout stream for the executed command
47 : * \see pipe_in()
48 : */
49 :
50 : std::string
51 0 : OksSystem::Executable::okssystem(const std::string& command)
52 : {
53 0 : OksSystem::Executable shell(SHELL_COMMAND);
54 0 : std::vector<std::string> params;
55 0 : params.push_back(SHELL_COMMAND_PARAM);
56 0 : params.push_back(command);
57 0 : return shell.pipe_in(params);
58 0 : } // std::string
59 :
60 0 : OksSystem::Executable::Executable(const OksSystem::File& file)
61 0 : : OksSystem::File(file)
62 : {
63 0 : }
64 0 : OksSystem::Executable::Executable(const char* filename)
65 0 : : OksSystem::File(filename)
66 : {
67 0 : }
68 0 : OksSystem::Executable::Executable(const std::string& filename)
69 0 : : OksSystem::File(filename)
70 : {
71 0 : }
72 0 : OksSystem::Executable::~Executable() {}
73 :
74 : /** Core execution method.
75 : * This method assumes the datastructures have been setup correctly for \c execv.
76 : * It basically adds some error handling to \c execv
77 : * \param argv array of arguments, with name of the executable in first position
78 : * \note this method should not be called directly
79 : */
80 :
81 : void
82 0 : OksSystem::Executable::exec(char** argv) const
83 : {
84 0 : ERS_PRECONDITION(argv);
85 0 : ERS_PRECONDITION(argv[0]);
86 0 : const int status = ::execv(argv[0], argv);
87 0 : throw OksSystem::ExecutionIssue(ERS_HERE, errno, argv[0], status);
88 : } // exec
89 :
90 : /** Core execution method.
91 : * This method assumes the datastructures have been setup correctly for \c execve.
92 : * It basically adds some error handling to \c execve.
93 : * Look at the \c execve man pages for details.
94 : * \param argv array of arguments, with name of the executable in first position
95 : * \param env array containing the environment the process will be started with
96 : */
97 : void
98 0 : OksSystem::Executable::exec(char** const argv, char** const env) const
99 : {
100 0 : ERS_PRECONDITION(argv);
101 0 : ERS_PRECONDITION(argv[0]);
102 0 : ERS_PRECONDITION(env);
103 0 : const int status = ::execve(argv[0], argv, env);
104 0 : throw OksSystem::ExecutionIssue(ERS_HERE, errno, argv[0], status);
105 : }
106 :
107 : /** Simple execution method.
108 : * This methods converts the vector of strings into the correct data structures for \c execv.
109 : * The \c argv structure is allocated dynamically and new string copied into it.
110 : */
111 :
112 : void
113 0 : OksSystem::Executable::exec(const param_collection& params) const
114 : {
115 0 : const int argc = params.size(); // number of parameters
116 0 : const int argclen = argc + 2; // size of array parameters + program name + null pointer
117 0 : char** argv = (char**)calloc(sizeof(char*), argclen);
118 0 : OKSSYSTEM_ALLOC_CHECK(argv, sizeof(char*) * argclen);
119 0 : const char* name = *this;
120 0 : argv[0] = strdup(name);
121 0 : OKSSYSTEM_ALLOC_CHECK(argv[0], strlen(name));
122 0 : for (int i = 0; i < argc; i++) {
123 0 : argv[i + 1] = strdup(params[i].c_str());
124 : } // loop over args
125 0 : argv[argc + 1] = 0;
126 0 : try {
127 0 : exec(argv);
128 0 : } catch (OksSystem::ExecutionIssue& ex) {
129 0 : for (int i = 0; argv[i] != 0; i++) {
130 0 : free(argv[i]);
131 : } // for
132 0 : free(argv);
133 0 : throw;
134 0 : } catch (ers::Issue& issue) { // there was a problem so we deallocate the argc array.
135 0 : for (int i = 0; argv[i] != 0; i++) {
136 0 : free(argv[i]);
137 : } // for
138 0 : free(argv);
139 0 : throw;
140 0 : } // catch
141 0 : } // exec
142 :
143 : /** This execution method calls the 'execve' function executing the
144 : * \param params the parameters to use when launching the executable
145 : * \param envs table of the environnement variables set for the executable
146 : */
147 :
148 : void
149 0 : OksSystem::Executable::exec(const param_collection& params, const env_collection& envs) const
150 : {
151 :
152 : // Elaborate the environment
153 0 : const unsigned int envArraySize = envs.size() + 1; // The last elements must be NULL
154 0 : char** const env = new char*[envArraySize];
155 :
156 0 : {
157 0 : const env_collection::const_iterator b = envs.begin();
158 0 : const env_collection::const_iterator e = envs.end();
159 0 : env_collection::const_iterator it;
160 :
161 0 : unsigned int counter = 0;
162 0 : for (it = b; it != e; ++it) {
163 0 : const std::string entry = it->first + "=" + it->second;
164 0 : env[counter] = new char[entry.size() + 1]; // Add the NULL terminator
165 0 : ::strcpy(env[counter], entry.c_str());
166 0 : ++counter;
167 0 : }
168 :
169 0 : env[envArraySize - 1] = (char*)0;
170 : }
171 :
172 : // Elaborate the paramenters
173 0 : const unsigned int paramArraySize = params.size() + 2; // Add the executable name and the NULL terminator
174 0 : char** const par = new char*[paramArraySize];
175 :
176 0 : {
177 0 : const std::string& binName = this->full_name();
178 0 : par[0] = new char[binName.size() + 1]; // Add the NULL terminator
179 0 : ::strcpy(par[0], binName.c_str());
180 :
181 0 : const param_collection::const_iterator b = params.begin();
182 0 : const param_collection::const_iterator e = params.end();
183 0 : param_collection::const_iterator it;
184 :
185 0 : unsigned int counter = 1;
186 0 : for (it = b; it != e; ++it) {
187 0 : const std::string& value = *it;
188 0 : par[counter] = new char[value.size() + 1]; // Add the NULL terminator
189 0 : ::strcpy(par[counter], value.c_str());
190 0 : ++counter;
191 : }
192 :
193 0 : par[paramArraySize - 1] = (char*)0;
194 : }
195 :
196 0 : try {
197 0 : exec(par, env);
198 0 : } catch (OksSystem::ExecutionIssue& ex) {
199 : // if we are here it means that the exec call failed!!!
200 : // Free the allocated memory
201 0 : for (unsigned int i = 0; i < envArraySize; ++i) {
202 0 : delete[] env[i];
203 : }
204 0 : delete[] env;
205 :
206 0 : for (unsigned int i = 0; i < paramArraySize; ++i) {
207 0 : delete[] par[i];
208 : }
209 0 : delete[] par;
210 :
211 : // Re-throw the exception
212 0 : throw ex;
213 0 : }
214 0 : }
215 :
216 : /** This method starts the executable in another process using \c fork
217 : * \param params the parameters to use when launching the executable
218 : * \return A process object representing the started process
219 : */
220 :
221 : OksSystem::Process
222 0 : OksSystem::Executable::start(const param_collection& params) const
223 : {
224 :
225 : // Block all signals before fork()
226 0 : sigset_t new_set;
227 0 : sigset_t old_set;
228 0 : sigfillset(&new_set);
229 0 : pthread_sigmask(SIG_SETMASK, &new_set, &old_set);
230 :
231 0 : const pid_t child_id = fork();
232 0 : if (0 == child_id) { // we are the child
233 :
234 : // Put some signals to their default
235 0 : signal(SIGTERM, SIG_DFL);
236 0 : signal(SIGINT, SIG_DFL);
237 :
238 : // Restore the original signal mask in child
239 0 : pthread_sigmask(SIG_SETMASK, &old_set, NULL);
240 :
241 0 : try {
242 0 : exec(params);
243 0 : } catch (OksSystem::ExecutionIssue& ex) {
244 0 : ers::warning(ex);
245 0 : _exit(EXIT_FAILURE);
246 0 : } catch (ers::Issue& ex) {
247 0 : ers::warning(ex);
248 0 : _exit(EXIT_FAILURE);
249 0 : }
250 :
251 : } // we are the child
252 0 : if (child_id > 0) { // we are the parent
253 :
254 : // Restore the original signal mask in parent
255 0 : pthread_sigmask(SIG_SETMASK, &old_set, NULL);
256 :
257 0 : return Process(child_id, to_string(params));
258 :
259 : } // we are the parent
260 :
261 : // Restore the original signal mask in case of a fork() failure
262 0 : pthread_sigmask(SIG_SETMASK, &old_set, NULL);
263 :
264 0 : throw OksSystem::OksSystemCallIssue(ERS_HERE, errno, "fork", ""); // We are screwed up
265 : } // start
266 :
267 : /** This method starts the executable in another process using \c fork. The parent will not wait on the child
268 : * termination.
269 : * \param params the parameters to use when launching the executable
270 : * \return A process object representing the started process
271 : */
272 :
273 : OksSystem::Process
274 0 : OksSystem::Executable::start_and_forget(const param_collection& params) const
275 : {
276 :
277 : // Block all signals before fork()
278 0 : sigset_t new_set;
279 0 : sigset_t old_set;
280 0 : sigfillset(&new_set);
281 0 : pthread_sigmask(SIG_SETMASK, &new_set, &old_set);
282 :
283 0 : signal(SIGCLD, SIG_IGN); /* now I don't have to wait()! */
284 :
285 0 : const pid_t child_id = fork();
286 0 : if (0 == child_id) { // we are the child
287 :
288 : // Put some signals to their default
289 0 : signal(SIGTERM, SIG_DFL);
290 0 : signal(SIGINT, SIG_DFL);
291 0 : signal(SIGCLD, SIG_DFL); /* Restore default SIGCLD handling in the child process */
292 :
293 : // Restore the original signal mask in child
294 0 : pthread_sigmask(SIG_SETMASK, &old_set, NULL);
295 :
296 0 : try {
297 0 : exec(params);
298 0 : } catch (OksSystem::ExecutionIssue& ex) {
299 0 : ers::warning(ex);
300 0 : _exit(EXIT_FAILURE);
301 0 : } catch (ers::Issue& ex) {
302 0 : ers::warning(ex);
303 0 : _exit(EXIT_FAILURE);
304 0 : }
305 :
306 : } // we are the child
307 0 : if (child_id > 0) { // we are the parent
308 :
309 : // Restore the original signal mask in parent
310 0 : pthread_sigmask(SIG_SETMASK, &old_set, NULL);
311 :
312 0 : return Process(child_id, to_string(params));
313 : } // we are the parent
314 :
315 : // Restore the original signal mask in case of a fork() failure
316 0 : pthread_sigmask(SIG_SETMASK, &old_set, NULL);
317 :
318 0 : throw OksSystem::OksSystemCallIssue(ERS_HERE, errno, "fork", ""); // We are screwed up
319 : } // start
320 :
321 : /** Copies the content of a file descriptor into a STL stream
322 : * \param fd the source file descriptor
323 : * \param target the target stream
324 : * \note a more efficient version could use the underlying STL buffer
325 : */
326 :
327 : void
328 0 : OksSystem::Executable::copy_fd(int fd, std::ostream& target)
329 : {
330 0 : while (true) {
331 0 : char buffer[256];
332 0 : long status = read(fd, buffer, sizeof(buffer));
333 0 : if (status <= 0)
334 0 : return;
335 0 : ERS_ASSERT(status <= (long)sizeof(buffer));
336 0 : for (int i = 0; i < status; i++) {
337 0 : target << (char)buffer[i];
338 : } // for
339 0 : } // while
340 : } // copy_fd
341 :
342 : /** \overload */
343 :
344 : std::string
345 0 : OksSystem::Executable::pipe_in(const param_collection& params) const
346 : {
347 :
348 0 : int input_pipe[2];
349 0 : int data_pipe[2];
350 0 : int error_pipe[2];
351 0 : const int input_pipe_status = pipe(input_pipe);
352 0 : if (input_pipe_status < 0)
353 0 : throw OksSystem::OksSystemCallIssue(ERS_HERE, errno, "pipe", "");
354 0 : const int data_pipe_status = pipe(data_pipe);
355 0 : if (data_pipe_status < 0)
356 0 : throw OksSystem::OksSystemCallIssue(ERS_HERE, errno, "pipe", "");
357 0 : const int error_pipe_status = pipe(error_pipe);
358 0 : if (error_pipe_status < 0)
359 0 : throw OksSystem::OksSystemCallIssue(ERS_HERE, errno, "pipe", "");
360 :
361 : // Block all signals before fork()
362 0 : sigset_t new_set;
363 0 : sigset_t old_set;
364 0 : sigfillset(&new_set);
365 0 : pthread_sigmask(SIG_SETMASK, &new_set, &old_set);
366 :
367 0 : const pid_t child_id = fork();
368 0 : if (0 == child_id) { // we are the child
369 :
370 : // Put some signals to their default
371 0 : signal(SIGTERM, SIG_DFL);
372 0 : signal(SIGINT, SIG_DFL);
373 :
374 : // Restore the original signal mask in child
375 0 : pthread_sigmask(SIG_SETMASK, &old_set, NULL);
376 :
377 0 : dup2(input_pipe[1], fileno(stdin));
378 0 : dup2(data_pipe[1], fileno(stdout));
379 0 : dup2(error_pipe[1], fileno(stderr));
380 :
381 0 : try {
382 0 : this->exec(params);
383 0 : } catch (OksSystem::ExecutionIssue& ex) {
384 0 : ers::warning(ex);
385 0 : _exit(EXIT_FAILURE);
386 0 : } catch (ers::Issue& ex) {
387 0 : ers::warning(ex);
388 0 : _exit(EXIT_FAILURE);
389 0 : }
390 :
391 : } // we are the child
392 0 : if (child_id > 0) { // we are the parent
393 :
394 : // Restore the original signal mask in parent
395 0 : pthread_sigmask(SIG_SETMASK, &old_set, NULL);
396 :
397 0 : Process child_process(child_id, to_string(params));
398 0 : close(input_pipe[1]);
399 0 : close(data_pipe[1]);
400 0 : close(error_pipe[1]);
401 0 : const int child_status = child_process.join();
402 0 : const int in_fd = input_pipe[0];
403 0 : const int err_fd = error_pipe[0];
404 0 : const int out_fd = data_pipe[0];
405 0 : std::ostringstream in_stream;
406 0 : std::ostringstream out_stream;
407 0 : std::ostringstream err_stream;
408 0 : copy_fd(in_fd, in_stream);
409 0 : copy_fd(out_fd, out_stream);
410 0 : copy_fd(err_fd, err_stream);
411 0 : close(in_fd);
412 0 : close(out_fd);
413 0 : close(err_fd);
414 0 : if (0 == child_status) {
415 0 : return out_stream.str();
416 : } // if
417 0 : std::string command = to_string(params);
418 0 : std::string error_str = err_stream.str();
419 0 : throw OksSystem::ExecutionIssue(ERS_HERE, errno, command.c_str(), child_status);
420 0 : } // we are the parent
421 :
422 : // Restore the original signal mask in case of a fork() failure
423 0 : pthread_sigmask(SIG_SETMASK, &old_set, NULL);
424 :
425 0 : return std::string();
426 : } // pipe_in
427 :
428 : /** This method executes the process and pipes stdout and stderr back and waits for execution termination.
429 : * If the return value is zero then the content of stdout is copied into a string and returned.
430 : * In case of a non-zero value, an exception is thrown.
431 : * This exception contains the return code and the content of stderr.
432 : * \return content of stdout
433 : * \param params the parameters to the executable
434 : * \param envs the environnement variables to set
435 : * \throw OksSystem::ExecutionIssue if command execution did not return 0.
436 : * \throw OksSystem::ExecFail if the exec okssystem call failed.
437 : * \throw OksSystem::PipeIssue if the pipe okssystem call failed.
438 : */
439 :
440 : std::string
441 0 : OksSystem::Executable::pipe_in(const param_collection& params, const env_collection& envs) const
442 : {
443 0 : OksSystem::Environment::set(envs);
444 0 : return pipe_in(params);
445 : } // pipe_in
446 :
447 : /** \overload */
448 :
449 : OksSystem::Process
450 0 : OksSystem::Executable::pipe_out(const param_collection& params,
451 : const File& input_file,
452 : const File& output_file,
453 : const File& error_file,
454 : mode_t perm) const
455 : {
456 :
457 : // Block all signals before fork()
458 0 : sigset_t new_set;
459 0 : sigset_t old_set;
460 0 : sigfillset(&new_set);
461 0 : pthread_sigmask(SIG_SETMASK, &new_set, &old_set);
462 :
463 0 : OksSystem::Descriptor in(
464 0 : &input_file, OksSystem::Descriptor::flags(true, false), perm); // May throw OksSystem::OpenFileIssue
465 0 : OksSystem::Descriptor out(&output_file, OksSystem::Descriptor::flags(false, true), perm);
466 0 : OksSystem::Descriptor err(&error_file, OksSystem::Descriptor::flags(false, true), perm);
467 :
468 0 : const pid_t child_id = fork();
469 0 : if (0 == child_id) { // we are the child
470 :
471 : // Put some signals to their default
472 0 : signal(SIGTERM, SIG_DFL);
473 0 : signal(SIGINT, SIG_DFL);
474 :
475 : // Restore the original signal mask in child
476 0 : pthread_sigmask(SIG_SETMASK, &old_set, NULL);
477 :
478 0 : try {
479 0 : ::dup2(in, ::fileno(stdin));
480 0 : ::dup2(out, ::fileno(stdout));
481 0 : ::dup2(err, ::fileno(stderr));
482 0 : ::close(in.fd());
483 0 : ::close(out.fd());
484 0 : ::close(err.fd());
485 0 : this->exec(params);
486 0 : } catch (OksSystem::ExecutionIssue& ex) {
487 0 : ers::warning(ex);
488 0 : _exit(EXIT_FAILURE);
489 0 : } catch (OksSystem::PosixIssue& ex) {
490 0 : ers::warning(ex);
491 0 : _exit(EXIT_FAILURE);
492 0 : } catch (ers::Issue& ex) {
493 0 : ers::warning(ex);
494 0 : _exit(EXIT_FAILURE);
495 0 : }
496 :
497 : } // we are the child
498 0 : if (child_id > 0) { // we are the parent
499 :
500 : // Restore the original signal mask in parent
501 0 : pthread_sigmask(SIG_SETMASK, &old_set, NULL);
502 :
503 0 : return Process(child_id, to_string(params));
504 : } // we are the parent
505 :
506 : // Restore the original signal mask in case of a fork() failure
507 0 : pthread_sigmask(SIG_SETMASK, &old_set, NULL);
508 :
509 0 : throw OksSystem::OksSystemCallIssue(ERS_HERE, errno, "fork", ""); // We are screwed up
510 0 : } // pipe_out
511 :
512 : /** Runs the executable and redirects the two output streams
513 : * \param params the parameters for the executable
514 : * \param envs the environnements for the executable
515 : * \param input_file the input file for stdin
516 : * \param output_file the output file for stdout
517 : * \param error_file the output file for stderr
518 : * \param perm permissions for both output streams
519 : */
520 :
521 : OksSystem::Process
522 0 : OksSystem::Executable::pipe_out(const param_collection& params,
523 : const env_collection& envs,
524 : const File& input_file,
525 : const File& output_file,
526 : const File& error_file,
527 : mode_t perm) const
528 : {
529 :
530 : // Block all signals before fork()
531 0 : sigset_t new_set;
532 0 : sigset_t old_set;
533 0 : sigfillset(&new_set);
534 0 : pthread_sigmask(SIG_SETMASK, &new_set, &old_set);
535 :
536 0 : OksSystem::Descriptor in(
537 0 : &input_file, OksSystem::Descriptor::flags(true, false), perm); // May throw OksSystem::OpenFileIssue
538 0 : OksSystem::Descriptor out(&output_file, OksSystem::Descriptor::flags(false, true), perm);
539 0 : OksSystem::Descriptor err(&error_file, OksSystem::Descriptor::flags(false, true), perm);
540 :
541 0 : const pid_t child_id = fork();
542 0 : if (0 == child_id) { // we are the child
543 :
544 : // Put some signals to their default
545 0 : signal(SIGTERM, SIG_DFL);
546 0 : signal(SIGINT, SIG_DFL);
547 :
548 : // Restore the original signal mask in child
549 0 : pthread_sigmask(SIG_SETMASK, &old_set, NULL);
550 :
551 0 : try {
552 0 : ::dup2(in, ::fileno(stdin));
553 0 : ::dup2(out, ::fileno(stdout));
554 0 : ::dup2(err, ::fileno(stderr));
555 0 : ::close(in.fd());
556 0 : ::close(out.fd());
557 0 : ::close(err.fd());
558 0 : this->exec(params, envs);
559 0 : } catch (OksSystem::ExecutionIssue& ex) {
560 0 : ers::warning(ex);
561 0 : _exit(EXIT_FAILURE);
562 0 : } catch (OksSystem::PosixIssue& ex) {
563 0 : ers::warning(ex);
564 0 : _exit(EXIT_FAILURE);
565 0 : } catch (ers::Issue& ex) {
566 0 : ers::warning(ex);
567 0 : _exit(EXIT_FAILURE);
568 0 : }
569 :
570 : } // we are the child
571 0 : if (child_id > 0) { // we are the parent
572 :
573 : // Restore the original signal mask in parent
574 0 : pthread_sigmask(SIG_SETMASK, &old_set, NULL);
575 :
576 0 : return Process(child_id, to_string(params));
577 : } // we are the parent
578 :
579 : // Restore the original signal mask in case of a fork() failure
580 0 : pthread_sigmask(SIG_SETMASK, &old_set, NULL);
581 :
582 0 : throw OksSystem::OksSystemCallIssue(ERS_HERE, errno, "fork", ""); // We are screwed up
583 :
584 0 : } // pipe_out
585 :
586 : /** This method starts the executable in another process using \c fork
587 : * \param params the parameters to use when launching the executable
588 : * \param envs table of the environnement variables set for the executable
589 : */
590 :
591 : OksSystem::Process
592 0 : OksSystem::Executable::start(const param_collection& params, const env_collection& envs) const
593 : {
594 :
595 : // Block all signals before fork()
596 0 : sigset_t new_set;
597 0 : sigset_t old_set;
598 0 : sigfillset(&new_set);
599 0 : pthread_sigmask(SIG_SETMASK, &new_set, &old_set);
600 :
601 0 : const pid_t child_id = fork();
602 0 : if (child_id == 0) { // we are the child
603 :
604 : // Put some signals to their default
605 0 : signal(SIGTERM, SIG_DFL);
606 0 : signal(SIGINT, SIG_DFL);
607 :
608 : // Restore the original signal mask in child
609 0 : pthread_sigmask(SIG_SETMASK, &old_set, NULL);
610 :
611 0 : try {
612 0 : exec(params, envs);
613 0 : } catch (OksSystem::ExecutionIssue& ex) {
614 0 : ers::warning(ex);
615 0 : _exit(EXIT_FAILURE);
616 0 : } catch (ers::Issue& ex) {
617 0 : ers::warning(ex);
618 0 : _exit(EXIT_FAILURE);
619 0 : }
620 :
621 : } // we are the child
622 0 : if (child_id > 0) { // we are the parent
623 :
624 : // Restore the original signal mask in parent
625 0 : pthread_sigmask(SIG_SETMASK, &old_set, NULL);
626 :
627 0 : return Process(child_id);
628 : } // we are the parent
629 :
630 : // Restore the original signal mask in case of a fork() failure
631 0 : pthread_sigmask(SIG_SETMASK, &old_set, NULL);
632 :
633 0 : throw OksSystem::OksSystemCallIssue(ERS_HERE, errno, "fork", ""); // We are screwed up
634 : } // start
635 :
636 : /** Converts the executable name and a list of parameters into a string,
637 : * suitable for display.
638 : * \param params the list of parameters
639 : * \return a string with command name and parameters separated by spaces
640 : */
641 :
642 : std::string
643 0 : OksSystem::Executable::to_string(const param_collection& params) const
644 : {
645 0 : std::ostringstream stream;
646 0 : stream << m_full_name;
647 0 : for (param_collection::const_iterator pos = params.begin(); pos != params.end(); ++pos) {
648 0 : stream << " " << (*pos);
649 : } // for
650 0 : return stream.str();
651 0 : } // to_string
|