00001 #ifndef DVUTIL_PROCESS_H 00002 #define DVUTIL_PROCESS_H 00003 // $Id: process.h,v 1.11 2008/03/13 21:17:13 dvermeir Exp $ 00004 #include <string> 00005 #include <stdexcept> 00006 #include <map> 00007 #include <sys/types.h> 00008 #include <dvutil/debug.h> 00009 00010 namespace Dv { 00011 namespace Util { 00012 /** A class representing a process. 00013 * It supports signaling and obtaining status. 00014 * Note that the constructor does not start up the process, for that 00015 * one should implement a subclass, with a constructor doing the 00016 * @c fork() etc. An example function that can be used to do this 00017 * is available in Dv::Util::Process:start. 00018 * 00019 * Example: 00020 * @code 00021 * Dv::Util::Process proc("ping www.bla.com"); 00022 * proc.start(); 00023 * std::cout << proc.status() << std::endl; 00024 * sleep(2); 00025 * proc.stop(); // stop (not kill) the process by sending STOP signal 00026 * sleep(2); 00027 * proc.resume(); // resume the process 00028 * sleep(2); 00029 * if (impatient) 00030 * proc.kill(); // send KILL signal 00031 * else 00032 * proc.wait(); // wait for process to actually finish 00033 * @endcode 00034 */ 00035 class Process: public DebugSlave { 00036 public: 00037 enum { NO_EXIT_STATUS = -2 }; 00038 00039 /** Process status */ 00040 enum Status { DEAD /** doesn't exist anymore */ , 00041 RUNNING /** also after resuming */, 00042 FINISHED /** finished normally, exit_status available */, 00043 STOPPED /** received SIGSTOP signal @sa Process::stop() */, 00044 SIGNALED /** e.g. using SIGKILL, @sa Process:kill() */, 00045 CONTINUING /** unused, could be supported under Linux 2.6 */ }; 00046 00047 /** Create a new process object. This function does not start up the 00048 * process; this job is left to subclasses or, alternatively, 00049 * to Dv::Util::Process::start. It simply stores the command to be executed. 00050 * Example: 00051 * @code 00052 * Dv::Util::Process proc("ping www.bla.com"); 00053 * proc.start(); 00054 * @endcode 00055 * @param command to be executed by the process. If empty, one can 00056 * use Dv::Util::Process:start to have the process execute a function 00057 * in the current program. 00058 * @param min_debug_level for when the object is connected 00059 * to a debug master 00060 * @sa Dv::Util::Process:start 00061 * @sa Dv::Debugable 00062 */ 00063 Process(const std::string& command = "", unsigned int min_debug_level = 1); 00064 00065 /** Start up a new process. 00066 * @return pid iff the process is running 00067 * @return 0 in the child process if the process is not running a command 00068 * @exception std::runtime_error if @c fork() failed. 00069 * @exception std::runtime_error if @c execl() failed. 00070 * @exception std::logic_error if the process is already running 00071 * 00072 * - If the process command is not empty, it will be executed using 00073 * @code 00074 * /bin/sh -c exec command 00075 * @endcode 00076 * Example: 00077 * @code 00078 * Dv::Util::Process proc("ping www.bla.com"); 00079 * proc.start(); 00080 * @endcode 00081 * - If the process command is empty, a @a fork() will be executed 00082 * and the function will return false in the child process. 00083 * This supports code such as the following. 00084 * @code 00085 * Dv::Util::Process p; 00086 * if (! p.start()) 00087 * return f(...); // in the child 00088 * p.wait(); // in the parent 00089 * @endcode 00090 * @sa Dv::Util::Process::Process 00091 */ 00092 int start() throw (std::runtime_error, std::logic_error); 00093 00094 /** @return process id of this process */ 00095 pid_t pid() const { return pid_; } 00096 00097 /** @return command executed by this process */ 00098 const std::string& command() const { return command_; } 00099 00100 /** @return exit status (-1..255) of a process that terminated normally 00101 * (i.e. was not signaled). 00102 * @warning If the process did not return normally or is still running, 00103 * NO_EXIT_STATUS will be returned. 00104 */ 00105 int exit_status() const { return exit_status_; } 00106 00107 /** @return signal that killed a process. 00108 * @return -1 if the process returned normally or is still running, 00109 */ 00110 int signaled() const { return signal_; } 00111 00112 /** @return true iff the process was killed using a SIGKILL signal 00113 * @sa Dv::Util::Process:kill 00114 */ 00115 bool killed() const; 00116 00117 /** @return true iff the process was stopped using a SIGSTOP signal 00118 * @sa Process::stop 00119 */ 00120 bool stopped() const; 00121 00122 /** Send a signal to this process. 00123 * @param signal to send 00124 * @param error_message to be used when throwing an exception 00125 * @exception std::runtime_error if @c kill(_,_) returns -1, e.g. if 00126 * the process does not exist anymore because it has already been 00127 * killed or waited upon. 00128 */ 00129 void signal(int signal, const std::string& error_message) const throw (std::runtime_error); 00130 00131 /** Send a SIGSTOP signal to this process. 00132 * @exception std::runtime_error inherited from Dv::Util::Process::signal 00133 * @sa Dv::Util::Process::signal 00134 */ 00135 void stop() const throw (std::runtime_error); 00136 00137 /** Send a SIGCONT signal to this process. 00138 * @exception std::runtime_error inherited from Dv::Util::Process::signal 00139 * @sa Dv::Util::Process::signal 00140 */ 00141 void resume() const throw (std::runtime_error); 00142 00143 /** Send a SIGKILL signal to this process. 00144 * @exception std::runtime_error inherited from Dv::Util::Process::signal 00145 * @sa Dv::Util::Process::signal 00146 */ 00147 void kill() const throw (std::runtime_error); 00148 00149 /** Wait for process to finish. 00150 * @return process status, one of @c FINISHED, @c DEAD, @c SIGNALED 00151 * @sa Dv::Util::Process::wait(bool) 00152 */ 00153 Status wait() const { return wait(false); } 00154 00155 /** Return current process status. 00156 * @warning There may be some delay between sending a signal and the 00157 * corresponding change of status. 00158 * @sa Dv::Util::Process::wait(bool) 00159 */ 00160 Status status() const { return wait(true); } 00161 00162 /** Destructor. If the process is still RUNNING or STOPPED, it will 00163 * be killed. 00164 */ 00165 virtual ~Process(); 00166 protected: 00167 /** Convert a status provided by @c waitpid to a Status, possibly 00168 * setting @a exit_status_ and @a signal_. 00169 * @param s status provided by @c waitpid 00170 * @return status of process 00171 */ 00172 Status status(int s) const; 00173 00174 /** Wrapper around @c waitpid. 00175 * @param nohang if true, waitpid will not wait for the process to 00176 * finish but just report the latest status change, if any. 00177 * @return current process status 00178 */ 00179 Status wait(bool nohang) const; 00180 /** This is protected so that subclasses can set it. */ 00181 pid_t pid_; 00182 private: 00183 Process(const Process&); 00184 Process& operator=(const Process&); 00185 std::string command_; 00186 int exit_status_; 00187 int signal_; 00188 }; 00189 } 00190 } 00191 00192 00193 #endif 00194
dvutil-1.0.10 | [ 5 December, 2009] |