LCOV - code coverage report
Current view: top level - okssystem/src - Executable.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 0.0 % 324 0
Test Date: 2026-07-12 15:23:06 Functions: 0.0 % 18 0

            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 &params) 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 &params, 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 &params) 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 &params) 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 &params) 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 &params, 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 &params, 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 &params, 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 &params, 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 &params) 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              : 
        

Generated by: LCOV version 2.0-1