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