X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Finspircd.cpp;h=6d82723612631b1796e6d5f39bb6a1bd4787c8ee;hb=9ad873886e518bf3621a88e8c48607ab79020c0a;hp=45649810b2cd7961008e66304af6e3e5bd6eef9c;hpb=399abe05ea337848da5d6b731217f7bb33a764f6;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/inspircd.cpp b/src/inspircd.cpp index 45649810b..6d8272361 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 void DeleteZero(T*& pr) @@ -137,6 +139,58 @@ namespace #endif } + // Attempts to fork into the background. + bool ForkIntoBackground() + { +#ifndef _WIN32 + // 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); + } +#endif + return true; + } + + // Increase the size of a core dump file to improve debugging problems. + void IncreaseCoreDumpSize() + { +#ifndef _WIN32 + errno = 0; + rlimit rl; + if (getrlimit(RLIMIT_CORE, &rl) == -1) + { + ServerInstance->Logs->Log("STARTUP", LOG_DEFAULT, "Unable to increase core dump size: getrlimit(RLIMIT_CORE) failed: %s", strerror(errno)); + return; + } + + rl.rlim_cur = rl.rlim_max; + if (setrlimit(RLIMIT_CORE, &rl) == -1) + ServerInstance->Logs->Log("STARTUP", LOG_DEFAULT, "Unable to increase core dump size: setrlimit(RLIMIT_CORE) failed: %s", strerror(errno)); +#endif + } + // Seeds the random number generator if applicable. void SeedRng(timespec ts) { @@ -147,6 +201,21 @@ namespace #endif } + // Sets handlers for various process signals. + void SetSignals() + { +#ifndef _WIN32 + signal(SIGALRM, SIG_IGN); + signal(SIGCHLD, SIG_IGN); + signal(SIGHUP, InspIRCd::SetSignal); + signal(SIGPIPE, SIG_IGN); + signal(SIGUSR1, SIG_IGN); + signal(SIGUSR2, SIG_IGN); + signal(SIGXFSZ, SIG_IGN); +#endif + signal(SIGTERM, InspIRCd::SetSignal); + } + // Required for returning the proper value of EXIT_SUCCESS for the parent process. void VoidSignalHandler(int) { @@ -190,65 +259,6 @@ void InspIRCd::Cleanup() Logs->CloseLogs(); } -void InspIRCd::SetSignals() -{ -#ifndef _WIN32 - signal(SIGALRM, SIG_IGN); - signal(SIGCHLD, SIG_IGN); - signal(SIGHUP, InspIRCd::SetSignal); - signal(SIGPIPE, SIG_IGN); - signal(SIGUSR1, SIG_IGN); - signal(SIGUSR2, SIG_IGN); - signal(SIGXFSZ, SIG_IGN); -#endif - 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); - - rlimit rl; - if (getrlimit(RLIMIT_CORE, &rl) == -1) - { - this->Logs->Log("STARTUP", LOG_DEFAULT, "Failed to getrlimit()!"); - return false; - } - rl.rlim_cur = rl.rlim_max; - - if (setrlimit(RLIMIT_CORE, &rl) == -1) - this->Logs->Log("STARTUP", LOG_DEFAULT, "setrlimit() failed, cannot increase coredump size."); - - return true; -#endif -} - void InspIRCd::WritePID(const std::string& filename, bool exitonfail) { #ifndef _WIN32 @@ -443,18 +453,18 @@ InspIRCd::InspIRCd(int argc, char** argv) } #endif - this->SetSignals(); + 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