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: 2025-12-21 13:07:08 Functions: 0.0 % 18 0

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

Generated by: LCOV version 2.0-1