diff --git a/Generators/include/Generators/GeneratorFileOrCmd.h b/Generators/include/Generators/GeneratorFileOrCmd.h index 1ab9bbdcce219..5a8f3411e883c 100644 --- a/Generators/include/Generators/GeneratorFileOrCmd.h +++ b/Generators/include/Generators/GeneratorFileOrCmd.h @@ -46,6 +46,12 @@ struct GeneratorFileOrCmd { * execute, but should not include pipes. */ void setCmd(const std::string& cmd) { mCmd = cmd; } + /** + * Set command child process PID + * + * @param cmdPid child process PID. + */ + void setCmdPid(const pid_t cmdPid) { mCmdPid = cmdPid; } /** * Set the number of events that a background command should * generate. This should come from @c SimConfig::getNEents. @@ -132,7 +138,14 @@ struct GeneratorFileOrCmd { * @return true if the background command line was executed, false * otherwise. */ - virtual bool executeCmdLine(const std::string& cmd) const; + virtual bool executeCmdLine(const std::string& cmd); + /** + * Terminates the background command using PID of the child + * process generated by fork. + * + * @return true if the process was terminated successfully + */ + virtual bool terminateCmd(); /** * Create a temporary file (and close it immediately). On success, * the list of file names is cleared and the name of the temporary @@ -236,6 +249,10 @@ struct GeneratorFileOrCmd { * Time in miliseconds between each wait for data */ int mWait = 500; + /** + * PID of the background command + */ + int mCmdPid = -1; }; } // namespace eventgen diff --git a/Generators/src/GeneratorFileOrCmd.cxx b/Generators/src/GeneratorFileOrCmd.cxx index 3ac3437f4f386..bc2083e025c14 100644 --- a/Generators/src/GeneratorFileOrCmd.cxx +++ b/Generators/src/GeneratorFileOrCmd.cxx @@ -16,7 +16,9 @@ // For fifo's and system call #include #include // POSIX only -#include // POISX only +#include // POSIX only +#include +#include #include // For filesystem operations #include @@ -115,14 +117,52 @@ std::string GeneratorFileOrCmd::makeCmdLine() const return s.str(); } // ----------------------------------------------------------------- -bool GeneratorFileOrCmd::executeCmdLine(const std::string& cmd) const +bool GeneratorFileOrCmd::executeCmdLine(const std::string& cmd) { LOG(info) << "Command line to execute: \"" << cmd << "\""; - int ret = std::system(cmd.c_str()); - if (ret != 0) { - LOG(fatal) << "Failed to spawn \"" << cmd << "\""; + // Fork a new process + pid_t pid = fork(); + if (pid == -1) { + LOG(fatal) << "Failed to fork process: " << std::strerror(errno); return false; } + + if (pid == 0) { + // Child process + setsid(); + execl("/bin/sh", "sh", "-c", cmd.c_str(), (char*)nullptr); + // If execl returns, there was an error, otherwise following lines will not be executed + LOG(fatal) << "Failed to execute command: " << std::strerror(errno); + _exit(EXIT_FAILURE); + } else { + // Parent process + setCmdPid(pid); + LOG(info) << "Child spawned process group is running with PID: " << mCmdPid; + } + return true; +} +// ----------------------------------------------------------------- +bool GeneratorFileOrCmd::terminateCmd() +{ + if (mCmdPid == -1) { + LOG(info) << "No command is currently running"; + return false; + } + + LOG(info) << "Terminating process ID group " << mCmdPid; + if (kill(-mCmdPid, SIGKILL) == -1) { + LOG(fatal) << "Failed to kill process: " << std::strerror(errno); + return false; + } + + // Wait for the process to terminate + int status; + if (waitpid(mCmdPid, &status, 0) == -1) { + LOG(fatal) << "Failed to wait for process termination: " << std::strerror(errno); + return false; + } + + mCmdPid = -1; // Reset the process ID return true; } // ----------------------------------------------------------------- diff --git a/Generators/src/GeneratorHepMC.cxx b/Generators/src/GeneratorHepMC.cxx index edaee66761658..371e0cf1acce1 100644 --- a/Generators/src/GeneratorHepMC.cxx +++ b/Generators/src/GeneratorHepMC.cxx @@ -65,6 +65,12 @@ GeneratorHepMC::~GeneratorHepMC() if (mEvent) { delete mEvent; } + if (not mCmd.empty()) { + // Must be executed before removing the temporary file + // otherwise the current child process might still be writing on it + // causing unwanted stdout messages which could slow down the system + terminateCmd(); + } removeTemp(); }