diff options
-rw-r--r-- | include/inspircd.h | 5 | ||||
-rw-r--r-- | src/inspircd.cpp | 82 | ||||
-rw-r--r-- | win/inspircd_win32wrapper.h | 1 |
3 files changed, 42 insertions, 46 deletions
diff --git a/include/inspircd.h b/include/inspircd.h index 775c201f9..97f8b3017 100644 --- a/include/inspircd.h +++ b/include/inspircd.h @@ -185,11 +185,6 @@ class CoreExport InspIRCd */ void SetSignals(); - /** Daemonize the ircd and close standard input/output streams - * @return True if the program daemonized succesfully - */ - bool DaemonSeed(); - /** The current time, updated in the mainloop */ struct timespec TIME; diff --git a/src/inspircd.cpp b/src/inspircd.cpp index b3198de57..022f06673 100644 --- a/src/inspircd.cpp +++ b/src/inspircd.cpp @@ -78,6 +78,8 @@ const char* ExitCodes[] = namespace { + void VoidSignalHandler(int); + // Deletes a pointer and then zeroes it. template<typename T> void DeleteZero(T*& pr) @@ -137,6 +139,38 @@ namespace #endif } + // Attempts to fork into the background. + bool ForkIntoBackground() + { + // We use VoidSignalHandler whilst forking to avoid breaking daemon scripts + // if the parent process exits with SIGTERM (15) instead of EXIT_STATUS_NOERROR (0). + signal(SIGTERM, VoidSignalHandler); + + errno = 0; + int childpid = fork(); + if (childpid < 0) + { + ServerInstance->Logs->Log("STARTUP", LOG_DEFAULT, "fork() failed: %s", strerror(errno)); + return false; + } + else if (childpid > 0) + { + // Wait until the child process kills the parent so that the shell prompt + // doesnt display over the output. Sending a kill with a signal of 0 just + // checks that the child pid is still running. If it is not then an error + // happened and the parent should exit. + while (kill(childpid, 0) != -1) + sleep(1); + exit(EXIT_STATUS_NOERROR); + } + else + { + setsid(); + signal(SIGTERM, InspIRCd::SetSignal); + return true; + } + } + // Increase the size of a core dump file to improve debugging problems. void IncreaseCoreDumpSize() { @@ -222,40 +256,6 @@ void InspIRCd::SetSignals() signal(SIGTERM, InspIRCd::SetSignal); } -bool InspIRCd::DaemonSeed() -{ -#ifdef _WIN32 - std::cout << "InspIRCd Process ID: " << con_green << GetCurrentProcessId() << con_reset << std::endl; - return true; -#else - // Do not use exit() here: It will exit with status SIGTERM which would break e.g. daemon scripts - signal(SIGTERM, VoidSignalHandler); - - int childpid = fork(); - if (childpid < 0) - return false; - else if (childpid > 0) - { - /* We wait here for the child process to kill us, - * so that the shell prompt doesnt come back over - * the output. - * Sending a kill with a signal of 0 just checks - * if the child pid is still around. If theyre not, - * they threw an error and we should give up. - */ - while (kill(childpid, 0) != -1) - sleep(1); - exit(EXIT_STATUS_NOERROR); - } - setsid (); - std::cout << "InspIRCd Process ID: " << con_green << getpid() << con_reset << std::endl; - - signal(SIGTERM, InspIRCd::SetSignal); - IncreaseCoreDumpSize(); - return true; -#endif -} - void InspIRCd::WritePID(const std::string& filename, bool exitonfail) { #ifndef _WIN32 @@ -452,16 +452,16 @@ InspIRCd::InspIRCd(int argc, char** argv) this->SetSignals(); - if (!Config->cmdline.nofork) + if (!Config->cmdline.nofork && !ForkIntoBackground()) { - if (!this->DaemonSeed()) - { - std::cout << "ERROR: could not go into daemon mode. Shutting down." << std::endl; - Logs->Log("STARTUP", LOG_DEFAULT, "ERROR: could not go into daemon mode. Shutting down."); - Exit(EXIT_STATUS_FORK); - } + std::cout << "ERROR: could not go into daemon mode. Shutting down." << std::endl; + Logs->Log("STARTUP", LOG_DEFAULT, "ERROR: could not go into daemon mode. Shutting down."); + Exit(EXIT_STATUS_FORK); } + std::cout << "InspIRCd Process ID: " << con_green << getpid() << con_reset << std::endl; + + IncreaseCoreDumpSize(); SocketEngine::RecoverFromFork(); /* During startup we read the configuration now, not in diff --git a/win/inspircd_win32wrapper.h b/win/inspircd_win32wrapper.h index e92339abf..6b69e1a6d 100644 --- a/win/inspircd_win32wrapper.h +++ b/win/inspircd_win32wrapper.h @@ -93,6 +93,7 @@ typedef SSIZE_T ssize_t; /* _popen, _pclose */ #define popen _popen #define pclose _pclose +#define getpid _getpid // warning: 'identifier' : class 'type' needs to have dll-interface to be used by clients of class 'type2' // Normally, this is a huge problem, but due to our new/delete remap, we can ignore it. |