aboutsummaryrefslogtreecommitdiffstats
path: root/src/inspircd.cpp
diff options
context:
space:
mode:
authorGravatar Sadie Powell2026-06-19 16:25:36 +0100
committerGravatar Sadie Powell2026-06-19 16:43:54 +0100
commitebcce68b6095ca9766641ce5dc00aae01d61de06 (patch)
tree1031bb5de5cbfd3be5ce37470d593bbe30154c95 /src/inspircd.cpp
parentRework 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.cpp55
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)