diff --git a/src/logger.hpp b/src/logger.hpp index 3b10bdf0c9aaea9fcaf3f83617081f8acd40382e..9b34d5a2e2d1e1622338d00c07d1c4caa001f5b1 100644 --- a/src/logger.hpp +++ b/src/logger.hpp @@ -131,6 +131,10 @@ public: return global_logger(); } + static inline void destroy_global_logger() { + global_logger().reset(); + } + // some macros to make it more convenient to use the global logger #define LOGGER_INFO(...) \ do { \ diff --git a/src/urd.cpp b/src/urd.cpp index 2a3f362acf4ec8cec79ccb0cfd001141a448bacd..b4077950b7524d245f52ae7d39f9e0b5d6e0443f 100644 --- a/src/urd.cpp +++ b/src/urd.cpp @@ -94,8 +94,23 @@ pid_t urd::daemonize() { return 0; } + // We need to destroy the global logger before calling fork. Otherwise the + // logger will not function properly since its internal thread will not + // be duplicated by fork(). Furthermore, if we don't destroy pre-fork() + // and attempt to replace it post-fork(), the logger destructor will attempt + // to join the (now invalid) thread and end up blocking forever. To avoid + // this (and since we want to be able to output messages from all + // processes), we destroy it now and recreate it post-fork() both in the + // parent process and in the child. + logger::destroy_global_logger(); + /* Fork off the parent process */ - if((pid = fork()) < 0) { + pid = fork(); + + // re-initialize logging facilities (post-fork) + init_logger(); + + if(pid < 0) { LOGGER_ERRNO("Failed to create child process"); exit(EXIT_FAILURE); } @@ -1536,7 +1551,7 @@ urd_error urd::check_shutdown() { int urd::run() { - // initialize logging facilities + // initialize logging facilities (pre-fork) init_logger(); // validate settings