diff --git a/src/MoqxPicoRelayServer.cpp b/src/MoqxPicoRelayServer.cpp index 51dad1b..62aed59 100644 --- a/src/MoqxPicoRelayServer.cpp +++ b/src/MoqxPicoRelayServer.cpp @@ -89,8 +89,16 @@ MoqxPicoRelayServer::MoqxPicoRelayServer( evb_(ioExecutor->getAllEventBases()[0].get()) {} MoqxPicoRelayServer::~MoqxPicoRelayServer() { + stop(); +} + +void MoqxPicoRelayServer::stop() { + if (!context_) { + return; + } context_->stop(); evb_->runImmediatelyOrRunInEventBaseThreadAndWait([this] { MoQPicoQuicEventBaseServer::stop(); }); + context_.reset(); } void MoqxPicoRelayServer::setStatsRegistry(std::shared_ptr registry) { diff --git a/src/MoqxPicoRelayServer.h b/src/MoqxPicoRelayServer.h index 2f66103..cda2fbf 100644 --- a/src/MoqxPicoRelayServer.h +++ b/src/MoqxPicoRelayServer.h @@ -33,6 +33,9 @@ class MoqxPicoRelayServer : public moxygen::MoQPicoQuicEventBaseServer { ~MoqxPicoRelayServer() override; + // Idempotent; safe to call from main and again from ~MoqxPicoRelayServer. + void stop() override; + void setStatsRegistry(std::shared_ptr registry); // Preferred entry point: binds the address from the stored ListenerConfig. diff --git a/src/MoqxRelayServer.cpp b/src/MoqxRelayServer.cpp index c774da4..aedc404 100644 --- a/src/MoqxRelayServer.cpp +++ b/src/MoqxRelayServer.cpp @@ -139,7 +139,16 @@ MoqxRelayServer::MoqxRelayServer( MoqxRelayServer::~MoqxRelayServer() { // Close incoming connections, drain worker EVBs, then destroy EVBs. + stop(); +} + +void MoqxRelayServer::stop() { + if (!context_) { + return; + } + // QuicServer::shutdown drives terminateClientSession, which uses context_. MoQServer::stop(); + context_.reset(); } void MoqxRelayServer::setStatsRegistry(std::shared_ptr registry) { diff --git a/src/MoqxRelayServer.h b/src/MoqxRelayServer.h index ef3ac98..0dd0fb5 100644 --- a/src/MoqxRelayServer.h +++ b/src/MoqxRelayServer.h @@ -26,6 +26,9 @@ class MoqxRelayServer : public moxygen::MoQServer { ~MoqxRelayServer() override; + // Idempotent; safe to call from main and again from ~MoqxRelayServer. + void stop() override; + void setStatsRegistry(std::shared_ptr registry); // Preferred entry point: binds the address from the stored ListenerConfig. diff --git a/src/main.cpp b/src/main.cpp index c9f4af4..ae0cebe 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -181,6 +181,14 @@ int main(int argc, char* argv[]) { // Stop admin last — allows a final metrics scrape during drain. adminServer.stop(); + // Stop servers before joining the IO pool — stop() needs worker EVBs alive, + // and lingering shared_ptr refs could delay ~MoqxRelayServer past that point. + for (auto& server : servers) { + server->stop(); + } + servers.clear(); + ioExecutor.reset(); + // === 14. Exit with appropriate code === return 0; }