diff options
| author | 2026-06-19 16:25:36 +0100 | |
|---|---|---|
| committer | 2026-06-19 16:43:54 +0100 | |
| commit | ebcce68b6095ca9766641ce5dc00aae01d61de06 (patch) | |
| tree | 1031bb5de5cbfd3be5ce37470d593bbe30154c95 /src/inspircd.cpp | |
| parent | Rework error reporting and shutting down. (diff) | |
Move server restart logic to the core.
- Properly clean up the process with Cleanup() instead of using
- DieRestart.
- Use close_range on modern Linux instead of the CLOEXEC hack.
Diffstat (limited to 'src/inspircd.cpp')
| -rw-r--r-- | src/inspircd.cpp | 55 |
1 files changed, 54 insertions, 1 deletions
diff --git a/src/inspircd.cpp b/src/inspircd.cpp index d75016242..afbd7947d 100644 --- a/src/inspircd.cpp +++ b/src/inspircd.cpp @@ -442,13 +442,66 @@ void InspIRCd::Exit(int status, const std::string& reason, const std::string& lo { // Tell modules that we're shutting down. const auto quitmsg = reason.empty() ? "Server shutting down" : reason; - FOREACH_MOD(OnShutdown, (quitmsg)); + FOREACH_MOD(OnShutdown, (quitmsg, false)); // Clean up all subsystems and then exit. this->Cleanup(quitmsg); InspIRCd::QuickExit(status, reason, logtype); } +std::string InspIRCd::Restart(const std::string& reason, const std::string& logtype) +{ + // Tell modules that we're restarting. + const auto quitmsg = reason.empty() ? "Server restarting" : reason; + FOREACH_MOD(OnShutdown, (quitmsg, true)); + + // Clean up all subsystems. + this->Cleanup(quitmsg); + + // HACK: Because execvp does not close any remaining open file descriptors + // we need ensure they are closed. On modern Linux we can do this with the + // close_range function but on older systems we need to fall back to setting + // the FD_CLOEXEC flag on all possible file descriptors. This is very slow + // but there's not much else we can do because we don't control the fd + // creation of all of our dependencies. + const auto first_fd = fileno(stderr) + 1; +#if defined HAS_CLOSE_RANGE && defined CLOSE_RANGE_CLOEXEC + close_range(first_fd, ~0, CLOSE_RANGE_CLOEXEC); +#elif defined FD_CLOEXEC + for (auto fd = SocketEngine::GetMaxFds(); fd >= size_t(first_fd); ++fd) + { + const auto flags = fcntl(int(fd), F_GETFD); + if (flags != 1) + fcntl(int(fd), F_SETFD, flags | FD_CLOEXEC); + } +#endif + + const auto should_print = isatty(fileno(stdout)); + if (should_print) + fmt::println(""); + + if (!reason.empty()) + { + if (!logtype.empty()) + ServerInstance->Logs.Critical(logtype, reason); + + if (should_print) + fmt::println("Server is restarting: {}.", reason); + } + + execvp(this->CommandLine.argv[0], this->CommandLine.argv); + + const std::string error = strerror(errno); + if (should_print) + { + if (!logtype.empty()) + ServerInstance->Logs.Critical(logtype, "Server restart failed: {}", error); + fmt::println("Server restart failed: {}.", error); + } + + return error; +} + void InspIRCd::WritePID() { if (!CommandLine.writepid) |
