diff options
| author | Dan Engelbrecht <[email protected]> | 2023-05-16 16:36:05 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-05-16 16:36:05 +0200 |
| commit | 72dd4a93de812030df9decdb338e1acd7b948e1d (patch) | |
| tree | 0fd66cd142eeb2bf61dd60a457b1343501f0511f | |
| parent | Additional trace instrumentation (#312) (diff) | |
| download | zen-72dd4a93de812030df9decdb338e1acd7b948e1d.tar.xz zen-72dd4a93de812030df9decdb338e1acd7b948e1d.zip | |
exit without SIGABRT if exception is thrown during startup (#313)
* Safeguard ZenServer::RequestExit() and ZenServer::Cleanup() when partially initialized
* Set exit code to non-zero if exception is thrown in ZenEntryPoint::Run()
* changelog
| -rw-r--r-- | CHANGELOG.md | 1 | ||||
| -rw-r--r-- | src/zenserver/zenserver.cpp | 48 |
2 files changed, 42 insertions, 7 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 8dabdaee9..bbb47480c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ - Feature: zenserver: Add command line option `--gc-projectstore-duration-seconds` to control GC life time of project store data - Bugfix: Improve error handling when processing requests in http asio - Bugfix: Error out if `test` is passed to zenserver in release builds (tests are only compiled in for debug) +- Bugfix: Gracefully exit with error code if problems arise during startup (used to cause abort termination) - Improvement: Added logging when bad chunks are detected in `BlockStore` - Improvement: `zen::SetCurrentThreadName` now also sets trace (Insights) thread name - Improvement: All thread pool threads now have names diff --git a/src/zenserver/zenserver.cpp b/src/zenserver/zenserver.cpp index 789b6f4a6..ac743adef 100644 --- a/src/zenserver/zenserver.cpp +++ b/src/zenserver/zenserver.cpp @@ -222,6 +222,15 @@ namespace utils { class ZenServer : public IHttpStatusProvider { public: + ~ZenServer() + { + m_IoContext.stop(); + if (m_IoRunner.joinable()) + { + m_IoRunner.join(); + } + } + int Initialize(const ZenServerOptions& ServerOptions, ZenServerState::ZenServerEntry* ServerEntry) { m_UseSentry = ServerOptions.NoSentry == false; @@ -489,14 +498,27 @@ public: void RequestExit(int ExitCode) { RequestApplicationExit(ExitCode); - m_Http->RequestExit(); + if (m_Http) + { + m_Http->RequestExit(); + } } void Cleanup() { ZEN_INFO(ZEN_APP_NAME " cleaning up"); - m_GcScheduler.Shutdown(); - m_Http->Close(); + try + { + m_GcScheduler.Shutdown(); + if (m_Http) + { + m_Http->Close(); + } + } + catch (std::exception& Ex) + { + ZEN_ERROR("exception thrown during Cleanup() in {}: '{}'", ZEN_APP_NAME, Ex.what()); + } } void SetDedicatedMode(bool State) { m_IsDedicatedMode = State; } @@ -1209,6 +1231,8 @@ ZenEntryPoint::Run() Server.SetTestMode(ServerOptions.IsTest); Server.SetDedicatedMode(ServerOptions.IsDedicated); + auto ServerCleanup = zen::MakeGuard([&Server] { Server.Cleanup(); }); + int EffectiveBasePort = Server.Initialize(ServerOptions, Entry); Entry->EffectiveListenPort = uint16_t(EffectiveBasePort); @@ -1242,6 +1266,16 @@ ZenEntryPoint::Run() ZEN_INFO("shutdown signal wait() failed"); } }}); + auto CleanupShutdown = zen::MakeGuard([&ShutdownEvent, &ShutdownThread] { + if (ShutdownEvent) + { + ShutdownEvent->Set(); + } + if (ShutdownThread && ShutdownThread->joinable()) + { + ShutdownThread->join(); + } + }); // If we have a parent process, establish the mechanisms we need // to be able to communicate readiness with the parent @@ -1259,14 +1293,14 @@ ZenEntryPoint::Run() }); Server.Run(); - Server.Cleanup(); - - ShutdownEvent->Set(); - ShutdownThread->join(); } catch (std::exception& e) { SPDLOG_CRITICAL("Caught exception in main: {}", e.what()); + if (!IsApplicationExitRequested()) + { + RequestApplicationExit(1); + } } ShutdownLogging(); |