+ // 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)
+ {
+#if defined _WIN32
+ srand(ts.tv_nsec ^ ts.tv_sec);
+#elif !defined HAS_ARC4RANDOM_BUF
+ srandom(ts.tv_nsec ^ ts.tv_sec);
+#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)
+ {
+ exit(EXIT_STATUS_NOERROR);
+ }