Back to index

nordugrid-arc-nox  1.1.0~rc6
Run_win32.cpp
Go to the documentation of this file.
00001 // -*- indent-tabs-mode: nil -*-
00002 
00003 #ifdef HAVE_CONFIG_H
00004 #include <config.h>
00005 #endif
00006 
00007 #include <glibmm.h>
00008 
00009 #include <iostream>
00010 #include <unistd.h>
00011 
00012 #include <arc/Thread.h>
00013 #include <arc/Logger.h>
00014 #include <arc/win32.h>
00015 #include "Run.h"
00016 
00017 namespace Arc {
00018 
00019   struct PipeThreadArg {
00020     HANDLE child;
00021     HANDLE parent;
00022   };
00023 
00024   void pipe_handler(void *arg);
00025 
00026   class RunPump {
00027     // NOP
00028   };
00029 
00030   class Pid {
00031     friend class Run;
00032   private:
00033     PROCESS_INFORMATION processinfo;
00034     Pid(void) {}
00035     Pid(int p_) {}
00036     Pid(const PROCESS_INFORMATION p_) {
00037       processinfo = p_;
00038     }
00039   };
00040 
00041   Run::Run(const std::string& cmdline)
00042     : working_directory("."),
00043       stdout_(-1),
00044       stderr_(-1),
00045       stdin_(-1),
00046       stdout_str_(NULL),
00047       stderr_str_(NULL),
00048       stdin_str_(NULL),
00049       stdout_keep_(false),
00050       stderr_keep_(false),
00051       stdin_keep_(false),
00052       pid_(NULL),
00053       argv_(Glib::shell_parse_argv(cmdline)),
00054       initializer_func_(NULL),
00055       initializer_arg_(NULL),
00056       kicker_func_(NULL),
00057       started_(false),
00058       running_(false),
00059       abandoned_(false),
00060       result_(-1) {
00061     pid_ = new Pid();
00062   }
00063 
00064   Run::Run(const std::list<std::string>& argv)
00065     : working_directory("."),
00066       stdout_(-1),
00067       stderr_(-1),
00068       stdin_(-1),
00069       stdout_str_(NULL),
00070       stderr_str_(NULL),
00071       stdin_str_(NULL),
00072       pid_(NULL),
00073       argv_(argv),
00074       initializer_func_(NULL),
00075       initializer_arg_(NULL),
00076       kicker_func_(NULL),
00077       started_(false),
00078       running_(false),
00079       abandoned_(false),
00080       result_(-1) {
00081     pid_ = new Pid();
00082   }
00083 
00084   Run::~Run(void) {
00085     if(*this) {
00086       if(!abandoned_) Kill(0);
00087       CloseStdout();
00088       CloseStderr();
00089       CloseStdin();
00090     };
00091     if(pid_) delete pid_;
00092   }
00093 
00094   bool Run::Start(void) {
00095     if (started_)
00096       return false;
00097     if (argv_.size() < 1)
00098       return false;
00099     try {
00100       running_ = true;
00101  
00102       SECURITY_ATTRIBUTES saAttr; 
00103       saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
00104       saAttr.bInheritHandle = TRUE; 
00105       saAttr.lpSecurityDescriptor = NULL; 
00106       
00107       STARTUPINFO startupinfo;
00108       memset(&startupinfo, 0, sizeof(startupinfo));
00109       startupinfo.cb = sizeof(STARTUPINFO);
00110 
00111       // TODO: stdin, stdout, stderr redirections (Apache/BSD license)
00112 
00113       char **args = const_cast<char**>(argv_.data());
00114       std::string cmd = "";
00115       for (int i = 0; args[i] != NULL; i++) {
00116         std::string a(args[i]);
00117         cmd += (a + " ");
00118       }
00119       int result = CreateProcess(NULL,
00120                                  (LPSTR)cmd.c_str(),
00121                                  NULL,
00122                                  NULL,
00123                                  TRUE,
00124                                  CREATE_NEW_PROCESS_GROUP | CREATE_NO_WINDOW | IDLE_PRIORITY_CLASS,
00125                                  NULL,
00126                                  (LPSTR)working_directory.c_str(),
00127                                  &startupinfo,
00128                                  &(pid_->processinfo));
00129 
00130       if (!result) {
00131         std::cout << "Spawn Error: " << GetOsErrorMessage() << std::endl;
00132         return false;
00133       }
00134       started_ = true;
00135     }
00136     catch (std::exception &e) {
00137         std::cerr << e.what() << std::endl;
00138         return false;
00139     }
00140     catch (Glib::Exception& e) {
00141       std::cerr << e.what() << std::endl;
00142     }
00143     return true;
00144   }
00145 
00146   void Run::Kill(int timeout) {
00147     if (!running_)
00148       return;
00149     // Kill with no merci
00150     running_ = false;
00151     TerminateProcess(pid_->processinfo.hProcess, 256);
00152   }
00153 
00154   void Run::Abandon(void) {
00155     if(*this) {
00156       CloseStdout();
00157       CloseStderr();
00158       CloseStdin();
00159       abandoned_=true;
00160     }
00161   }
00162 
00163   bool Run::stdout_handler(Glib::IOCondition) {
00164     return true;
00165   }
00166 
00167   bool Run::stderr_handler(Glib::IOCondition) {
00168     return true;
00169   }
00170 
00171   bool Run::stdin_handler(Glib::IOCondition) {
00172     return true;
00173   }
00174 
00175   void Run::child_handler(Glib::Pid, int result) {
00176   }
00177 
00178   void Run::CloseStdout(void) {
00179     if (stdout_ != -1)
00180       ::close(stdout_);
00181     stdout_ = -1;
00182   }
00183 
00184   void Run::CloseStderr(void) {
00185     if (stderr_ != -1)
00186       ::close(stderr_);
00187     stderr_ = -1;
00188   }
00189 
00190   void Run::CloseStdin(void) {
00191     if (stdin_ != -1)
00192       ::close(stdin_);
00193     stdin_ = -1;
00194   }
00195 
00196   int Run::ReadStdout(int /*timeout*/, char *buf, int size) {
00197     if (stdout_ == -1)
00198       return -1;
00199     // TODO: do it through context for timeout
00200     return ::read(stdout_, buf, size);
00201   }
00202 
00203   int Run::ReadStderr(int /*timeout*/, char *buf, int size) {
00204     if (stderr_ == -1)
00205       return -1;
00206     // TODO: do it through context for timeout
00207     return ::read(stderr_, buf, size);
00208   }
00209 
00210   int Run::WriteStdin(int /*timeout*/, const char *buf, int size) {
00211     return 0;
00212   }
00213 
00214   bool Run::Running(void) {
00215     Wait(0);
00216     return running_;
00217   }
00218 
00219   bool Run::Wait(int timeout) {
00220     if (!started_)
00221       return false;
00222     if (!running_)
00223       return true;
00224     // XXX timeouted wait
00225     return true;
00226   }
00227 
00228   bool Run::Wait(void) {
00229     if (!started_)
00230       return false;
00231     if (!running_)
00232       return true;
00233     WaitForSingleObject(pid_->processinfo.hProcess, INFINITE);
00234     WaitForSingleObject(pid_->processinfo.hThread, INFINITE);
00235     CloseHandle(pid_->processinfo.hThread);
00236     CloseHandle(pid_->processinfo.hProcess);
00237     running_ = false;
00238     return true;
00239   }
00240 
00241   void Run::AssignStdout(std::string& str) {
00242     if (!running_)
00243       stdout_str_ = &str;
00244   }
00245 
00246   void Run::AssignStderr(std::string& str) {
00247     if (!running_)
00248       stderr_str_ = &str;
00249   }
00250 
00251   void Run::AssignStdin(std::string& str) {
00252     if (!running_)
00253       stdin_str_ = &str;
00254   }
00255 
00256   void Run::KeepStdout(bool keep) {
00257     if (!running_)
00258       stdout_keep_ = keep;
00259   }
00260 
00261   void Run::KeepStderr(bool keep) {
00262     if (!running_)
00263       stderr_keep_ = keep;
00264   }
00265 
00266   void Run::KeepStdin(bool keep) {
00267     if (!running_)
00268       stdin_keep_ = keep;
00269   }
00270 
00271   void Run::AssignInitializer(void (*initializer_func)(void *arg), void *initializer_arg) {
00272     if (!running_) {
00273       initializer_arg_ = initializer_arg;
00274       initializer_func_ = initializer_func;
00275     }
00276   }
00277 
00278   void Run::AssignKicker(void (*kicker_func)(void *arg), void *kicker_arg) {
00279     if (!running_) {
00280       kicker_arg_ = kicker_arg;
00281       kicker_func_ = kicker_func;
00282     }
00283   }
00284 
00285 }