From dbafdf67440947e6bfb7f1a80c246641614b74e1 Mon Sep 17 00:00:00 2001 From: Thulinma Date: Fri, 19 Mar 2021 22:36:27 +0100 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 | 11 ++++++----- 5 files changed, 36 insertions(+), 7 deletions(-) diff --git a/lib/procs.cpp b/lib/procs.cpp index 851014ab..3ce41860 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 60d07b8e..2a606cb0 100644 --- a/src/controller/controller.cpp +++ b/src/controller/controller.cpp @@ -596,10 +596,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; @@ -609,6 +609,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 f5f3c8e6..30805bcc 100644 --- a/src/input/input.cpp +++ b/src/input/input.cpp @@ -310,11 +310,8 @@ namespace Mist { streamStatus.master = false; if (streamStatus){streamStatus.mapped[0] = STRMSTAT_INIT;} } - //Abandon all semaphores, ye who enter here. - playerLock.abandon(); - pullLock.abandon(); - if (!preRun()){return 0;} - int ret = run(); + int ret = 0; + if (preRun()){ret = run();} if (playerLock){ playerLock.unlink(); char pageName[NAME_BUFFER_SIZE]; @@ -322,14 +319,17 @@ namespace Mist { streamStatus.init(pageName, 1, true, false); streamStatus.close(); } + playerLock.unlink(); pullLock.unlink(); return ret; } 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]; @@ -344,6 +344,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!