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

Generated by: LCOV version 2.0-1