Skip to content

Commit 03913e4

Browse files
committed
Changed child process spawning mechanism
Fundamental to be able to kill the child process spawned by CMD functionality of GeneratorFileOrCmd generator. This was not so useful when the destructors were not called at the end of the simulation
1 parent e5532f5 commit 03913e4

File tree

3 files changed

+68
-5
lines changed

3 files changed

+68
-5
lines changed

Generators/include/Generators/GeneratorFileOrCmd.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ struct GeneratorFileOrCmd {
4646
* execute, but should not include pipes.
4747
*/
4848
void setCmd(const std::string& cmd) { mCmd = cmd; }
49+
/**
50+
* Set command child process PID
51+
*
52+
* @param cmdPid child process PID.
53+
*/
54+
void setCmdPid(const pid_t cmdPid) { mCmdPid = cmdPid; }
4955
/**
5056
* Set the number of events that a background command should
5157
* generate. This should come from @c SimConfig::getNEents.
@@ -132,7 +138,14 @@ struct GeneratorFileOrCmd {
132138
* @return true if the background command line was executed, false
133139
* otherwise.
134140
*/
135-
virtual bool executeCmdLine(const std::string& cmd) const;
141+
virtual bool executeCmdLine(const std::string& cmd);
142+
/**
143+
* Terminates the background command using PID of the child
144+
* process generated by fork.
145+
*
146+
* @return true if the process was terminated successfully
147+
*/
148+
virtual bool terminateCmd();
136149
/**
137150
* Create a temporary file (and close it immediately). On success,
138151
* the list of file names is cleared and the name of the temporary
@@ -236,6 +249,10 @@ struct GeneratorFileOrCmd {
236249
* Time in miliseconds between each wait for data
237250
*/
238251
int mWait = 500;
252+
/**
253+
* PID of the background command
254+
*/
255+
int mCmdPid = -1;
239256
};
240257

241258
} // namespace eventgen

Generators/src/GeneratorFileOrCmd.cxx

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#include <cstdlib>
1818
#include <sys/types.h> // POSIX only
1919
#include <sys/stat.h> // POISX only
20+
#include <signal.h>
21+
#include <sys/wait.h>
2022
#include <cstdio>
2123
// For filesystem operations
2224
#include <filesystem>
@@ -115,14 +117,52 @@ std::string GeneratorFileOrCmd::makeCmdLine() const
115117
return s.str();
116118
}
117119
// -----------------------------------------------------------------
118-
bool GeneratorFileOrCmd::executeCmdLine(const std::string& cmd) const
120+
bool GeneratorFileOrCmd::executeCmdLine(const std::string& cmd)
119121
{
120122
LOG(info) << "Command line to execute: \"" << cmd << "\"";
121-
int ret = std::system(cmd.c_str());
122-
if (ret != 0) {
123-
LOG(fatal) << "Failed to spawn \"" << cmd << "\"";
123+
// Fork a new process
124+
pid_t pid = fork();
125+
if (pid == -1) {
126+
LOG(fatal) << "Failed to fork process: " << std::strerror(errno);
127+
return false;
128+
}
129+
130+
if (pid == 0) {
131+
// Child process
132+
setsid();
133+
execl("/bin/sh", "sh", "-c", cmd.c_str(), (char*)nullptr);
134+
// If execl returns, there was an error, otherwise following lines will not be executed
135+
LOG(fatal) << "Failed to execute command: " << std::strerror(errno);
136+
_exit(EXIT_FAILURE);
137+
} else {
138+
// Parent process
139+
setCmdPid(pid);
140+
LOG(info) << "Child spawned process group is running with PID: " << mCmdPid;
141+
}
142+
return true;
143+
}
144+
// -----------------------------------------------------------------
145+
bool GeneratorFileOrCmd::terminateCmd()
146+
{
147+
if (mCmdPid == -1) {
148+
LOG(info) << "No command is currently running";
149+
return false;
150+
}
151+
152+
LOG(info) << "Terminating process ID group " << mCmdPid;
153+
if (kill(-mCmdPid, SIGKILL) == -1) {
154+
LOG(fatal) << "Failed to kill process: " << std::strerror(errno);
124155
return false;
125156
}
157+
158+
// Wait for the process to terminate
159+
int status;
160+
if (waitpid(mCmdPid, &status, 0) == -1) {
161+
LOG(fatal) << "Failed to wait for process termination: " << std::strerror(errno);
162+
return false;
163+
}
164+
165+
mCmdPid = -1; // Reset the process ID
126166
return true;
127167
}
128168
// -----------------------------------------------------------------

Generators/src/GeneratorHepMC.cxx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ GeneratorHepMC::~GeneratorHepMC()
6565
if (mEvent) {
6666
delete mEvent;
6767
}
68+
if (not mCmd.empty()) {
69+
// Must be executed before removing the temporary file
70+
// otherwise the current child process might still be writing on it
71+
// causing unwanted stdout messages which could slow down the system
72+
terminateCmd();
73+
}
6874
removeTemp();
6975
}
7076

0 commit comments

Comments
 (0)