libassa
3.5.0
|
00001 // -*- c++ -*- 00002 //------------------------------------------------------------------------------ 00003 // Fork.h 00004 //------------------------------------------------------------------------------ 00005 // Copyright (C) 1997-2002,2005 Vladislav Grinchenko 00006 // 00007 // This library is free software; you can redistribute it and/or 00008 // modify it under the terms of the GNU Library General Public 00009 // License as published by the Free Software Foundation; either 00010 // version 2 of the License, or (at your option) any later version. 00011 //------------------------------------------------------------------------------ 00012 #ifndef IS_FORK_H 00013 #define IS_FORK_H 00014 00015 #include <unistd.h> // fork 00016 #include <stdlib.h> 00017 #include <errno.h> 00018 #include <sys/types.h> 00019 #include <signal.h> 00020 00021 #ifndef WIN32 00022 # include <sys/wait.h> 00023 #endif 00024 00025 #include <list> 00026 using std::list; 00027 00028 /* Sun Solaris 2.6 has wait4(3C) function definition missing 00029 * from its header files. The function, however, is in the 00030 * standard library. Testing this scenario would require 00031 * writing custom m4 macro. 00032 */ 00033 #if defined(__sun) 00034 #include <sys/time.h> 00035 #include <sys/resource.h> 00036 extern "C" pid_t 00037 wait4(pid_t pid, int *statusp, int options, struct rusage *rusage); 00038 #endif 00039 00040 00041 #include "assa/Assure.h" 00042 #include "assa/Singleton.h" 00043 #include "assa/EventHandler.h" 00044 #include "assa/SigHandler.h" 00045 #include "assa/SigAction.h" 00046 00047 namespace ASSA { 00048 00058 class ChildStatusHandler : public EventHandler 00059 { 00060 public: 00061 ChildStatusHandler () 00062 : m_exit_status (-1), m_caught (false) { /* no-op */ } 00063 00064 int handle_signal (int signum_); 00065 00069 int exit_status () const { return m_exit_status; } 00070 00073 bool caught () const { return m_caught; } 00074 00075 private: 00076 int m_exit_status; 00077 bool m_caught; 00078 }; 00079 00086 class Fork { 00087 public: 00091 enum state_t { 00092 KILL_ON_EXIT, 00093 WAIT_ON_EXIT, 00094 LEAVE_ALONE 00095 }; 00096 00099 enum wait4status_t { 00100 IGNORE_STATUS, 00101 COLLECT_STATUS 00103 }; 00104 00105 #if !defined(WIN32) 00106 00116 Fork (state_t exit_action_ = WAIT_ON_EXIT, 00117 wait4status_t catch_status_ = COLLECT_STATUS); 00118 00124 ~Fork() { trace_with_mask("Fork::~Fork",FORK); } 00125 00130 bool isParent() const { return m_pid ? true : false; } 00131 00136 bool isChild() const { return !m_pid ? true : false; } 00137 00142 pid_t getChildPID() const { 00143 trace_with_mask("Fork::getChildPID",FORK); 00144 return m_pid; 00145 } 00146 00151 int get_exit_status () const { return m_chstath.exit_status (); } 00152 00153 #endif // !defined(WIN32) 00154 00170 static int fork_exec (const string& cmd_, 00171 const string& args_, 00172 wait4status_t wait_for_completion_, 00173 bool ignore_output_ = false); 00174 00175 #if !defined(WIN32) 00176 private: 00178 pid_t m_pid; 00179 00181 SigHandler m_local_sh; 00182 00184 ChildStatusHandler m_chstath; 00185 00187 SigAction m_old_disp; 00188 00189 #endif // !defined(WIN32) 00190 00191 }; 00192 00195 class fnode_t { 00196 public: 00198 fnode_t (pid_t pid_, Fork::state_t state_) 00199 : m_pid(pid_), m_state(state_) 00200 { 00201 trace_with_mask("fnode_t::fnode_t",FORK); 00202 } 00203 00205 pid_t getPID() const 00206 { 00207 trace_with_mask("fnode_t::getPID",FORK); 00208 return m_pid; 00209 } 00210 00212 bool needKill() const 00213 { 00214 trace_with_mask("fnode_t::needKill",FORK); 00215 return m_state == Fork::KILL_ON_EXIT ? true : false; 00216 } 00217 private: 00219 pid_t m_pid; 00220 00222 Fork::state_t m_state; 00223 }; 00224 00231 class ForkList : public Singleton < ForkList > 00232 { 00233 public: 00235 ForkList () { trace_with_mask("ForkList::ForkList",FORK); } 00236 00238 ~ForkList(); 00239 00241 list< fnode_t* > m_list; 00242 }; 00243 00244 } // end namespace ASSA 00245 00246 #endif // IS_FORK_H 00247 00248 00249 00250 00251