From bffd81f27e8a88a40afa32d089c9a6356bf668ae Mon Sep 17 00:00:00 2001 From: Thulinma Date: Wed, 21 Apr 2021 17:56:16 +0200 Subject: [PATCH] Correct handling of reaper thread in forking binaries --- lib/procs.cpp | 22 ++++++++++++++++++++++ lib/procs.h | 2 ++ lib/util.cpp | 3 +++ src/controller/controller.cpp | 5 +++-- src/input/input.cpp | 3 +++ 5 files changed, 33 insertions(+), 2 deletions(-) diff --git a/lib/procs.cpp b/lib/procs.cpp index 72e01ddf..e25137d1 100644 --- a/lib/procs.cpp +++ b/lib/procs.cpp @@ -157,6 +157,28 @@ void Util::Procs::exit_handler() { 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 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 guard(plistMutex); + if (handler_set){ + thread_handler = true; + reaper_thread = new tthread::thread(grim_reaper, 0); + } +} + /// Sets up exit and childsig handlers. /// Spawns grim_reaper. exit handler despawns grim_reaper /// Called by every Start* function. diff --git a/lib/procs.h b/lib/procs.h index e7edb4d0..05eb484a 100644 --- a/lib/procs.h +++ b/lib/procs.h @@ -26,6 +26,8 @@ namespace Util { static bool childRunning(pid_t p); static tthread::thread * reaper_thread; static bool handler_set; ///< If true, the sigchld handler has been setup. + static void fork_prepare(); + static void fork_complete(); static void setHandler(); static std::string getOutputOf(char * const * argv); static std::string getOutputOf(std::deque & argDeq); diff --git a/lib/util.cpp b/lib/util.cpp index 2a4402dc..ebae4f77 100644 --- a/lib/util.cpp +++ b/lib/util.cpp @@ -245,8 +245,10 @@ namespace Util{ int pipeErr[2]; if (pipe(pipeErr) >= 0){ //Start reading log messages from the unnamed pipe + Util::Procs::fork_prepare(); pid_t pid = fork(); if (pid == 0) { //child + Util::Procs::fork_complete(); close(pipeErr[1]); // close the unneeded pipe file descriptor //Close all sockets in the socketList for (std::set::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)); exit(0); } + Util::Procs::fork_complete(); if (pid == -1){ FAIL_MSG("Failed to fork child process for log handling!"); }else{ diff --git a/src/controller/controller.cpp b/src/controller/controller.cpp index 61ef20e2..542decce 100644 --- a/src/controller/controller.cpp +++ b/src/controller/controller.cpp @@ -475,10 +475,10 @@ int main(int argc, char **argv){ Controller::conf.activate(); uint64_t reTimer = 0; while (Controller::conf.is_active){ + Util::Procs::fork_prepare(); pid_t pid = fork(); if (pid == 0){ - Util::Procs::handler_set = false; - Util::Procs::reaper_thread = 0; + Util::Procs::fork_complete(); { struct sigaction new_action; new_action.sa_sigaction = handleUSR1; @@ -488,6 +488,7 @@ int main(int argc, char **argv){ } return main_loop(argc, argv); } + Util::Procs::fork_complete(); if (pid == -1){ FAIL_MSG("Unable to spawn controller process!"); return 2; diff --git a/src/input/input.cpp b/src/input/input.cpp index 0afbf895..feefb207 100644 --- a/src/input/input.cpp +++ b/src/input/input.cpp @@ -157,8 +157,10 @@ namespace Mist { config->activate(); uint64_t reTimer = 0; while (config->is_active){ + Util::Procs::fork_prepare(); pid_t pid = fork(); if (pid == 0){ + Util::Procs::fork_complete(); if (playerLock){ //Re-init streamStatus, previously closed char pageName[NAME_BUFFER_SIZE]; @@ -173,6 +175,7 @@ namespace Mist { if (!preRun()){return 0;} return run(); } + Util::Procs::fork_complete(); if (pid == -1){ FAIL_MSG("Unable to spawn input process"); //We failed. Release the kra... semaphores!