Correct handling of reaper thread in forking binaries

This commit is contained in:
Thulinma 2021-04-21 17:56:16 +02:00
parent ddd9e8c67d
commit bffd81f27e
5 changed files with 33 additions and 2 deletions

View file

@ -157,6 +157,28 @@ void Util::Procs::exit_handler() {
FAIL_MSG("Giving up with %d children left.", (int)listcopy.size()); FAIL_MSG("Giving up with %d children left.", (int)listcopy.size());
} }
// Joins the reaper thread, if any, before a fork
void Util::Procs::fork_prepare(){
tthread::lock_guard<tthread::mutex> guard(plistMutex);
if (handler_set){
thread_handler = false;
if (reaper_thread){
reaper_thread->join();
delete reaper_thread;
reaper_thread = 0;
}
}
}
/// Restarts reaper thread if it was joined
void Util::Procs::fork_complete(){
tthread::lock_guard<tthread::mutex> guard(plistMutex);
if (handler_set){
thread_handler = true;
reaper_thread = new tthread::thread(grim_reaper, 0);
}
}
/// Sets up exit and childsig handlers. /// Sets up exit and childsig handlers.
/// Spawns grim_reaper. exit handler despawns grim_reaper /// Spawns grim_reaper. exit handler despawns grim_reaper
/// Called by every Start* function. /// Called by every Start* function.

View file

@ -26,6 +26,8 @@ namespace Util {
static bool childRunning(pid_t p); static bool childRunning(pid_t p);
static tthread::thread * reaper_thread; static tthread::thread * reaper_thread;
static bool handler_set; ///< If true, the sigchld handler has been setup. static bool handler_set; ///< If true, the sigchld handler has been setup.
static void fork_prepare();
static void fork_complete();
static void setHandler(); static void setHandler();
static std::string getOutputOf(char * const * argv); static std::string getOutputOf(char * const * argv);
static std::string getOutputOf(std::deque<std::string> & argDeq); static std::string getOutputOf(std::deque<std::string> & argDeq);

View file

@ -245,8 +245,10 @@ namespace Util{
int pipeErr[2]; int pipeErr[2];
if (pipe(pipeErr) >= 0){ if (pipe(pipeErr) >= 0){
//Start reading log messages from the unnamed pipe //Start reading log messages from the unnamed pipe
Util::Procs::fork_prepare();
pid_t pid = fork(); pid_t pid = fork();
if (pid == 0) { //child if (pid == 0) { //child
Util::Procs::fork_complete();
close(pipeErr[1]); // close the unneeded pipe file descriptor close(pipeErr[1]); // close the unneeded pipe file descriptor
//Close all sockets in the socketList //Close all sockets in the socketList
for (std::set<int>::iterator it = Util::Procs::socketList.begin(); it != Util::Procs::socketList.end(); ++it){ for (std::set<int>::iterator it = Util::Procs::socketList.begin(); it != Util::Procs::socketList.end(); ++it){
@ -264,6 +266,7 @@ namespace Util{
Util::logParser(pipeErr[0], true_stderr, isatty(true_stderr)); Util::logParser(pipeErr[0], true_stderr, isatty(true_stderr));
exit(0); exit(0);
} }
Util::Procs::fork_complete();
if (pid == -1){ if (pid == -1){
FAIL_MSG("Failed to fork child process for log handling!"); FAIL_MSG("Failed to fork child process for log handling!");
}else{ }else{

View file

@ -475,10 +475,10 @@ int main(int argc, char **argv){
Controller::conf.activate(); Controller::conf.activate();
uint64_t reTimer = 0; uint64_t reTimer = 0;
while (Controller::conf.is_active){ while (Controller::conf.is_active){
Util::Procs::fork_prepare();
pid_t pid = fork(); pid_t pid = fork();
if (pid == 0){ if (pid == 0){
Util::Procs::handler_set = false; Util::Procs::fork_complete();
Util::Procs::reaper_thread = 0;
{ {
struct sigaction new_action; struct sigaction new_action;
new_action.sa_sigaction = handleUSR1; new_action.sa_sigaction = handleUSR1;
@ -488,6 +488,7 @@ int main(int argc, char **argv){
} }
return main_loop(argc, argv); return main_loop(argc, argv);
} }
Util::Procs::fork_complete();
if (pid == -1){ if (pid == -1){
FAIL_MSG("Unable to spawn controller process!"); FAIL_MSG("Unable to spawn controller process!");
return 2; return 2;

View file

@ -157,8 +157,10 @@ namespace Mist {
config->activate(); config->activate();
uint64_t reTimer = 0; uint64_t reTimer = 0;
while (config->is_active){ while (config->is_active){
Util::Procs::fork_prepare();
pid_t pid = fork(); pid_t pid = fork();
if (pid == 0){ if (pid == 0){
Util::Procs::fork_complete();
if (playerLock){ if (playerLock){
//Re-init streamStatus, previously closed //Re-init streamStatus, previously closed
char pageName[NAME_BUFFER_SIZE]; char pageName[NAME_BUFFER_SIZE];
@ -173,6 +175,7 @@ namespace Mist {
if (!preRun()){return 0;} if (!preRun()){return 0;}
return run(); return run();
} }
Util::Procs::fork_complete();
if (pid == -1){ if (pid == -1){
FAIL_MSG("Unable to spawn input process"); FAIL_MSG("Unable to spawn input process");
//We failed. Release the kra... semaphores! //We failed. Release the kra... semaphores!