00001 #ifndef Impala_Process_Manager4Posix_h
00002 #define Impala_Process_Manager4Posix_h
00003
00004 #include <map>
00005 #include <strstream>
00006
00007
00008 #include <sys/types.h>
00009 #include <sys/time.h>
00010 #include <sys/wait.h>
00011 #include <sys/resource.h>
00012 #include <unistd.h>
00013 #include <signal.h>
00014 #include <errno.h>
00015 #include <string.h>
00017
00018 #include "Basis/ILog.h"
00019 #include "Basis/String.h"
00020 #include "Basis/StringList.h"
00021
00022 #include "Process/Manager.h"
00023
00024 namespace Impala
00025 {
00026 namespace Process
00027 {
00028
00029
00030
00031
00032
00033
00034
00035
00036 class Manager4Posix : public Manager
00037 {
00038 typedef struct {int stateCode; int exitCode;} ProcessData;
00039
00040 ILOG_VAR_DECL;
00041 std::map<int, ProcessData> mProcesses;
00042
00043 public:
00044
00045 Manager4Posix()
00046 {
00047 ILOG_DEBUG("Creating instance");
00048 }
00049
00050 virtual ~Manager4Posix()
00051 {
00052 std::map<int, ProcessData>::iterator iter = mProcesses.begin();
00053 while (iter != mProcesses.end())
00054 {
00055 int pid = iter->first;
00056 Kill(pid);
00057 iter++;
00058 }
00059 ILOG_DEBUG("Destroying instance");
00060 }
00061
00062 int Create(const std::string& cmdLine, std::string application)
00063 {
00064 ILOG_INFO("Create [" << cmdLine << "][" << application << "]");
00065 pid_t pid = fork();
00066 if(pid==-1)
00067 {
00068
00069
00070 char buff[256];
00071 if( strerror_r( errno, buff, 256 ) == 0 ) {
00072 ILOG_ERROR("Could not fork process"<<buff);
00073 }
00074
00075 }
00076 else if(pid==0)
00077 {
00078
00079
00080
00081 ILOG_INFO("Child Process Running");
00082
00084
00085
00086
00087
00088
00089
00091
00092
00093 StringList argList(cmdLine,' ');
00094 int argc=argList.size()+1;
00095 if (argc < 2)
00096 {
00097 ILOG_ERROR("The cmd line must contain at least the name of the application to run");
00098 abort();
00099 }
00100
00101 char** argv;
00102 argv = new char*[argc];
00103
00104 int a=0;
00105 StringList::const_iterator i=argList.begin();
00106 std::string application = *i;
00107 for ( ; i!=argList.end(); i++)
00108 {
00109 argv[a] = new char[(*i).length() + 1];
00110 sprintf(argv[a],(*i).c_str());
00111 a++;
00112
00113 }
00114 argv[a] = (char*)NULL;
00115
00116 execvp(application.c_str(),argv);
00117
00118 char buff[256];
00119 if( strerror_r( errno, buff, 256 ) == 0 ) {
00120 ILOG_ERROR("Could not start application"<<buff);
00121 }
00122 abort();
00123 }
00124 else
00125 {
00126
00127
00128 ILOG_INFO("The process is forked, child pid is: "<<pid);
00129 ProcessData data;
00130 data.stateCode = STATE_RUNNING;
00131 mProcesses[pid] = data;
00132 return pid;
00133 }
00134
00135 }
00136
00137 bool
00138 IsRunning(int pid)
00139 {
00140
00141 if(mProcesses[pid].stateCode == STATE_RUNNING)
00142 {
00143
00144 int status;
00145 int ret=waitpid(pid, &status, WNOHANG);
00146
00147 if(ret==0)
00148 return true;
00149 else
00150 {
00151 SetExitCode(pid,status,ret);
00152 return false;
00153 }
00154 }
00155 else
00156 return false;
00157 }
00158
00159 int GetManagedProcessCount() const
00160 {
00161 return mProcesses.size();
00162 }
00163
00164 bool IsTerminated(int pid)
00165 {
00166 return !IsRunning(pid);
00167 }
00168
00169 void Sleep(int sec)
00170 {
00171 sleep(sec);
00172 }
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246 void Kill(int pid)
00247 {
00248 if (IsRunning(pid))
00249 kill(pid,SIGTERM);
00250 }
00251
00252 void Remove(int pid)
00253 {
00254 Kill(pid);
00255 mProcesses.erase(pid);
00256 }
00257
00258 int GetState(int pid)
00259 {
00260 if (IsRunning(pid))
00261 return STATE_RUNNING;
00262
00263 return mProcesses[pid].stateCode;
00264 }
00265
00266 int GetExitCode(int pid)
00267 {
00268 if (IsRunning(pid))
00269 {
00270 ILOG_ERROR("Process is still running; exit code not available (yet)");
00271 throw "process is still running";
00272 }
00273 return mProcesses[pid].exitCode;
00274 }
00275
00276 private:
00277
00278
00279 void
00280 SetExitCode(int pid,int status,int ret)
00281 {
00282
00283 if(ret==pid)
00284 {
00285 if(WIFEXITED(status))
00286 {
00287 ILOG_DEBUG("Process exited normally!");
00288
00289
00290 mProcesses[pid].exitCode = WEXITSTATUS(status);
00291
00292 if(WEXITSTATUS(status)==0)
00293 mProcesses[pid].stateCode = STATE_TERM_SUCCESS;
00294 else
00295 mProcesses[pid].stateCode = STATE_TERM_ERROR;
00296 }
00297 else if(WIFSIGNALED(status))
00298 {
00299 ILOG_ERROR("Process received a signal!");
00300
00301 mProcesses[pid].stateCode = STATE_TERM_ABNORMAL;
00302 mProcesses[pid].exitCode = WTERMSIG(status);
00303 }
00304 }else{
00305
00306
00307
00308
00309
00310
00311 char buff[256];
00312 if( strerror_r( errno, buff, 256 ) == 0 ) {
00313 ILOG_ERROR("waitpid failed:"<<buff);
00314 }
00315 }
00316 }
00317
00318
00319 };
00320
00321 ILOG_VAR_INIT(Manager4Posix, Impala.Process);
00322
00323 }
00324 }
00325
00326 #endif