Back to index

nordugrid-arc-nox  1.1.0~rc6
run.cpp
Go to the documentation of this file.
00001 #ifdef HAVE_CONFIG_H
00002 #include <config.h>
00003 #endif
00004 
00005 #include <glibmm.h>
00006 #include <sys/types.h>
00007 #include <sys/stat.h>
00008 #include <unistd.h>
00009 #include <arc/Run.h>
00010 #include <arc/StringConv.h>
00011 #ifdef WIN32
00012 #include <arc/win32.h>
00013 #else
00014 #include <sys/wait.h>
00015 #endif
00016 
00017 #include "paul.h"
00018 
00019 namespace Paul
00020 {
00021 
00022 static std::string save_filename(const std::string &in)
00023 {
00024     std::string out = "";
00025     for (int i = 0; i < in.size(); i++) {
00026         out += in[i];
00027         if ((in[i] == '\\' && i < in.size() - 1 && in[i+1] != '\\') 
00028             || (in[i] == '\\' && i > 0 && in[i-1] != '\\')) {
00029             out += in[i];
00030         }
00031     }
00032     return out;
00033 }
00034 
00035 bool PaulService::run(Job &j)
00036 {
00037     logger_.msg(Arc::VERBOSE, "Start process");
00038     Arc::XMLNode jd = j.getJSDL()["JobDescription"];
00039     Arc::XMLNode app = jd["Application"]["POSIXApplication"];
00040     if (app == false) {
00041         app = jd["Application"]["HPCProfileApplication"];
00042     }
00043     if (app == false) {
00044         logger_.msg(Arc::ERROR, "Invalid JSDL! Missing application section");
00045         if (j.getStatus() != KILLED || j.getStatus() != KILLING) {
00046             logger_.msg(Arc::VERBOSE, "%s set exception", j.getID());
00047             j.setStatus(FAILED);
00048         }
00049         return false;
00050     }
00051     std::string exec = (std::string)app["Executable"];
00052     // XXX protection against ../../ stuff in the executable and all kind
00053     // of path
00054     if (exec.empty()) {
00055         logger_.msg(Arc::ERROR, "Empty executable");
00056         if (j.getStatus() != KILLED || j.getStatus() != KILLING) {
00057             logger_.msg(Arc::VERBOSE, "%s set exception", j.getID());
00058             j.setStatus(FAILED);
00059         }
00060         return false;    
00061     }
00062     Arc::XMLNode arg;
00063     std::string arg_str = " ";
00064     for (int i=0; (arg = app["Argument"][i]) != false; i++) {
00065         arg_str += (std::string)arg + " ";
00066     }
00067 
00068     std::string std_in = (std::string)app["Input"];
00069     std::string std_out = (std::string)app["Output"];
00070     std::string std_err = (std::string)app["Error"];
00071     std::string cmd;
00072 
00073     std::string wd = Glib::build_filename(configurator.getJobRoot(), j.getID());
00074     mkdir(wd.c_str(), 0700);
00075     if (!Glib::path_is_absolute(exec)) {
00076 #ifdef WIN32
00077         size_t found = exec.find_last_of(".");
00078         std::string extension = exec.substr(found+1);
00079         extension = Arc::upper(extension);
00080         if (extension == "BAT") {
00081           std::string cmd_path = Glib::find_program_in_path("cmd");
00082           logger_.msg(Arc::VERBOSE, "Windows cmd path: %s", cmd_path);
00083           cmd = cmd_path + " /c " + exec;
00084         }
00085         if (extension != "BAT")
00086 #endif
00087         cmd = Glib::build_filename(wd, exec);
00088         chmod(cmd.c_str(), 0700);
00089 #ifndef WIN32
00090         cmd = "./" + exec + arg_str;
00091 #else
00092         cmd += (" " + arg_str);
00093 #endif
00094     } else {
00095         cmd = exec + arg_str;
00096     }
00097 #ifdef WIN32
00098     cmd = save_filename(cmd);
00099 #endif
00100     logger_.msg(Arc::VERBOSE, "Cmd: %s", cmd);
00101 
00102     Arc::Run *run = NULL;
00103     try {
00104         run = new Arc::Run(cmd);
00105         if (!std_in.empty())
00106           run->AssignStdin(std_in);
00107         if (!std_out.empty())
00108           run->AssignStdout(std_out);
00109         if (!std_err.empty())
00110           run->AssignStderr(std_err);
00111         run->AssignWorkingDirectory(wd);
00112         logger_.msg(Arc::VERBOSE, "Command: %s", cmd);
00113         if(!run->Start()) {
00114             logger_.msg(Arc::ERROR, "Cannot start application");
00115             goto error;
00116         }
00117         j.setStatus(RUNNING);
00118         runq[j.getID()] = run;
00119         if(run->Wait()) {
00120             logger_.msg(Arc::VERBOSE, "StdOut: %s", std_out);
00121             logger_.msg(Arc::VERBOSE, "StdErr: %s", std_err);
00122             if (run != NULL) {
00123                 //logger_.msg(Arc::VERBOSE, "delete run");
00124 
00125                 // TODO: erase should be delayed
00126                 //runq.erase(j.getID());
00127 
00128                 delete run;
00129                 run = NULL;
00130             }
00131             logger_.msg(Arc::VERBOSE, "return from run");
00132             if (j.getStatus() != KILLED && j.getStatus() != KILLING) {
00133                 logger_.msg(Arc::VERBOSE, "%s set finished", j.getID());
00134                 j.setStatus(FINISHED);
00135             }
00136             return true;
00137         } else {
00138             logger_.msg(Arc::ERROR, "Error during the application run");
00139             goto error;
00140         }
00141         /* int r = */ run->Result();
00142     } catch (std::exception &e) {
00143         logger_.msg(Arc::ERROR, "Exception: %s", e.what());
00144         goto error;
00145     } catch (Glib::SpawnError &e) {
00146         logger_.msg(Arc::ERROR, "SpawnError");
00147         goto error;
00148     } catch (Glib::SpawnError &e) {
00149         std::cerr << e.what() << std::endl;
00150     }
00151 
00152 error:
00153     if (j.getStatus() != KILLED && j.getStatus() != KILLING) {
00154         logger_.msg(Arc::VERBOSE, "%s set exception", j.getID());
00155         j.setStatus(FAILED);
00156     }
00157     if (run != NULL) {
00158         runq.erase(j.getID());
00159         delete run;
00160         run = NULL;
00161     }
00162     return false;
00163 }
00164 
00165 }