LCOV - code coverage report
Current view: top level - okssystem/src - Process.cpp (source / functions) Coverage Total Hit
Test: code.result Lines: 0.0 % 86 0
Test Date: 2025-12-21 13:07:08 Functions: 0.0 % 20 0

            Line data    Source code
       1              : /*
       2              :  *  Process.cxx
       3              :  *  OksSystem 
       4              :  *
       5              :  *  Created by Matthias Wiesmann on 18.01.05.
       6              :  *  Copyright 2005 CERN. All rights reserved.
       7              :  *
       8              :  */
       9              :  
      10              : #include <sys/wait.h>
      11              : #include <sys/types.h>
      12              : #include <unistd.h>
      13              : #include <sysexits.h>
      14              : 
      15              : #include <iostream>
      16              : #include <sstream>
      17              : 
      18              : #include "ers/ers.hpp"
      19              : 
      20              : #include "okssystem/exceptions.hpp"
      21              : #include "okssystem/Process.hpp"
      22              : 
      23              : 
      24              : const int OksSystem::Process::TEST_BASE_VALUE = 182;/**< Lowest value for test manager result code  */
      25              : const int OksSystem::Process::TEST_MAX_VALUE = 186; /**< Highest value for test manager result code */
      26              : 
      27              : const int OksSystem::Process::TERMINATION_WAIT = 100000; /**< Wait time before deciding a termination signal did not work (in nanoseconds) */
      28              : 
      29              : const char * const OksSystem::Process::SYS_EXITS_NAMES[] = { "command line usage error", "data format error", "cannot open input", "addressee unknown", "host name unknown", "service unavailable", "internal software error", "okssystem error", 
      30              :     "critical OS file missing", "can't create (user) output file", "input/output error", "temp failure; user is invited to retry", "remote error in protocol", "permission denied ", "configuration error" };
      31              : const char * const OksSystem::Process::TEST_EXITS_NAMES[] = { "undefined test", "test failed", "test unresolved", "test untested", "unsupported test" };
      32              : const char * const OksSystem::Process::OK_EXIT_NAME = "ok";
      33              : 
      34              : OksSystem::Process *OksSystem::Process::s_instance = 0;
      35              : 
      36              : /** Gives textual representation of exit values. 
      37              :   * This method recognises return codes from \c sysexits and the values returned by the text-manager 
      38              :   * \param return_value the integer returned by a program
      39              :   * \return a pointer to the string desribing the code, or a null pointer if the code is not recognised
      40              :   */
      41              : 
      42            0 : const char* OksSystem::Process::exit_text(int return_value) {
      43            0 :     if ( 0==return_value) return OK_EXIT_NAME;
      44            0 :     if ((return_value >= EX__BASE)  && (return_value <= EX__MAX)) return SYS_EXITS_NAMES[return_value-EX__BASE];
      45            0 :     if ((return_value >= TEST_BASE_VALUE) && (return_value <= TEST_MAX_VALUE)) return TEST_EXITS_NAMES[return_value-TEST_BASE_VALUE];
      46              :     return 0;
      47              : } // return_text
      48              : 
      49              : /** Builds a pretty string for an exit value 
      50              :   * \param return_value the integer returned by a program
      51              :   * \return if the code is recognised by \c exit_text, this text and the number between parenthesis 
      52              :   *         if not, the \c return_value converter into a string 
      53              :   */
      54              : 
      55            0 : std::string OksSystem::Process::exit_pretty(int return_value) {
      56            0 :     std::ostringstream stream;
      57            0 :     const char* text = OksSystem::Process::exit_text(return_value);
      58            0 :     if (text) {
      59            0 :         stream << text << '(' << return_value << ')';
      60              :     } else {
      61            0 :         stream << return_value ;
      62              :     }
      63            0 :     return stream.str(); 
      64            0 : } // exit_string
      65              : 
      66              : 
      67              : /** Default current process instance 
      68              :   * If needed the instance is created 
      69              :   * \return singleton instance for current process
      70              :   */
      71              : 
      72            0 : const OksSystem::Process *OksSystem::Process::instance() throw() {
      73            0 :     if (0==s_instance) {
      74            0 :         s_instance = new OksSystem::Process(); 
      75              :     } // if
      76            0 :     return s_instance;
      77              : } // instance
      78              : 
      79              : 
      80              : /** Sets the process name of the current process 
      81              :   */
      82              : 
      83            0 : void OksSystem::Process::set_name(const std::string &name) throw() {
      84            0 :     (void) instance();
      85            0 :     s_instance->m_process_name = name;
      86            0 : } // set_name
      87              : 
      88              : 
      89              : /** Constructor from current process 
      90              :  *  For the current process, the singleton factory method \c instance should be used 
      91              :  */
      92              : 
      93            0 : OksSystem::Process::Process() {
      94            0 :     m_process_id = ::getpid();
      95            0 : } // Process
      96              : 
      97              : /** Copy constructor 
      98              :   * \param other original instance 
      99              :   */
     100              : 
     101            0 : OksSystem::Process::Process(const Process &other) {
     102            0 :     m_process_id = other.m_process_id;
     103            0 :     m_process_name = other.m_process_name;
     104            0 : } // Process
     105              : 
     106              : /** Constructor for pid
     107              :   * \param id pid of the process
     108              :   */
     109              : 
     110            0 : OksSystem::Process::Process(pid_t id){
     111            0 :     m_process_id = id;
     112            0 : } // Process 
     113              : 
     114              : /** Constructor from pid and process name 
     115              :   * \param id pid of the process 
     116              :   * \param name display name of the process 
     117              :   */
     118              : 
     119            0 : OksSystem::Process::Process(pid_t id, const std::string &name) {
     120            0 :     m_process_id = id;
     121            0 :     m_process_name = name;
     122            0 : } 
     123              : 
     124              : 
     125              : /** Destructor 
     126              :   */
     127              : 
     128            0 : OksSystem::Process::~Process() throw() {
     129            0 :     m_process_id = 0;
     130            0 : } // ~Process
     131              : 
     132              : /** Cast operator - converts to process-id 
     133              :   */
     134              : 
     135            0 : OksSystem::Process::operator pid_t() const throw() {
     136            0 :     return m_process_id;
     137              : } // operator pid_t
     138              : 
     139              : 
     140              : /** Waits for a process to terminate. 
     141              :   * If the process terminates normally, the return value is the termination status of the process. 
     142              :   * If the process stops or is signaled, an SignalIssue is thrown. 
     143              :   * \return the termination status of the process 
     144              :   */
     145              : 
     146            0 : int OksSystem::Process::join(bool throw_non_zero) const {
     147            0 :     ERS_PRECONDITION(! equals(*instance())); 
     148            0 :     int status;
     149            0 :     errno = 0;
     150            0 :     pid_t pid = ::waitpid(m_process_id,&status,0); 
     151            0 :     if (pid!=m_process_id) {
     152            0 :         std::string message = "on process " + this->to_string();
     153            0 :         throw OksSystem::OksSystemCallIssue( ERS_HERE, errno, "waitpid", message.c_str() ); 
     154            0 :     } // if 
     155            0 :     if (WIFEXITED(status)) {
     156            0 :         int exit_status = WEXITSTATUS(status);
     157            0 :         if ((throw_non_zero==false) || (exit_status==0)) return exit_status;
     158            0 :         throw OksSystem::TerminationIssue(ERS_HERE, errno, exit_status);
     159              :     } // exit status
     160            0 :     if (WIFSIGNALED(status)) throw OksSystem::SignalIssue(ERS_HERE,errno,WTERMSIG(status));
     161            0 :     if (WIFSTOPPED(status)) throw OksSystem::SignalIssue(ERS_HERE,errno,WSTOPSIG(status));
     162            0 :     return WEXITSTATUS(status);
     163              : } // join
     164              : 
     165              : /** Sends a signal to the process 
     166              :   * \param signal_number number of the signal 
     167              :   */
     168              : 
     169            0 : void OksSystem::Process::signal(int signal_number) const {
     170            0 :     const int status = ::kill(m_process_id,signal_number);
     171            0 :     if (status < 0) {
     172            0 :       std::string message = "on process " + this->to_string();
     173            0 :       throw OksSystem::OksSystemCallIssue(ERS_HERE, errno, "kill", message.c_str());
     174            0 :     }
     175            0 : } // signal
     176              : 
     177              : /** Checks if the process actually exists on the host
     178              :   * \return true if the process exists 
     179              :   * \note currently the check is done by sending signal 0 to the process
     180              :   *       in case of failure, we know process does not exist 
     181              :   */
     182              : 
     183            0 : bool OksSystem::Process::exists() const {
     184            0 :     const int status = ::kill(m_process_id,0);
     185            0 :     return (status>=0);
     186              : } // exists
     187              : 
     188              : /** Checks if two process are equal 
     189              :   * \param other the process to compare this process to
     190              :   * \return true if both proceses are equal (same pid).
     191              :   */
     192              : 
     193            0 : bool OksSystem::Process::equals(const Process &other) const throw() {
     194            0 :     return m_process_id == other.m_process_id;
     195              : } // equals
     196              : 
     197              : /** Terminates a process 
     198              :   * Termination is implemented by
     199              :   * \li sending the TERM signal
     200              :   */
     201              : 
     202            0 : void OksSystem::Process::terminate() const {
     203              :   /*
     204              :     struct timespec wait_time;
     205              :     struct timespec remain_time;
     206              :     wait_time.tv_sec = 0;
     207              :     wait_time.tv_nsec = TERMINATION_WAIT;
     208              :   */
     209            0 :     if (exists()) {
     210            0 :         signal(SIGTERM);
     211              :     }
     212            0 :     return;
     213              : } 
     214              : 
     215              : /* This is a piece of crap 
     216              :     nanosleep(&wait_time,&remain_time); 
     217              :     if (exists()) {
     218              :         signal(SIGQUIT);
     219              :     } else {
     220              :         return;
     221              :     } //
     222              :     nanosleep(&wait_time,&remain_time); 
     223              :     if (exists()) {
     224              :         signal(SIGKILL);
     225              :     } // exists
     226              : } // terminate
     227              : */
     228              : /** Builds a string description of the process 
     229              :   * \return textual description
     230              :   */
     231              : 
     232            0 : std::string OksSystem::Process::to_string() const throw() {
     233            0 :     std::ostringstream stream;
     234            0 :     if (! m_process_name.empty()) {
     235            0 :         stream << m_process_name << ' ';
     236              :     } 
     237            0 :     stream << "pid: " << m_process_id;
     238            0 :     return stream.str(); 
     239            0 : } // to_string
     240              : 
     241              : /** \return the process id for the process 
     242              :   */
     243              : 
     244            0 : pid_t OksSystem::Process::process_id() const throw() { return m_process_id;} 
     245              : 
     246              : /** Streaming operator
     247              :   * \param out destination stream
     248              :   * \param proc the process to stream 
     249              :   * \see Process::to_string()
     250              :   */
     251              : 
     252            0 : std::ostream& operator<<(std::ostream& out, const OksSystem::Process &proc) {
     253            0 :     out << proc.to_string();
     254            0 :     return out;
     255              : } // operator<<
     256              : 
     257              : /** Comparison operator 
     258              :   * \param a first process to compare
     259              :   * \param b second process to compare 
     260              :   * \return true if they are equal 
     261              :   * \see OksSystem::Process::equals
     262              :   */
     263              : 
     264            0 : bool operator ==(const OksSystem::Process &a, const OksSystem::Process &b)  throw() {
     265            0 :     return a.equals(b);
     266              : } // operator ==
     267              : 
     268              : /** Comparison operator 
     269              :   * \param a first process to compare
     270              :   * \param b second process to compare 
     271              :   * \return false if they are equal 
     272              :   * \see OksSystem::Process::equals
     273              :   */
     274              : 
     275            0 : bool operator !=(const OksSystem::Process &a, const OksSystem::Process &b)  throw() {
     276            0 :     return ! a.equals(b); 
     277              : } // operator !=
     278              : 
     279              : 
        

Generated by: LCOV version 2.0-1