From 6df7bce35e84f91c868face688587c26a3765c7e Mon Sep 17 00:00:00 2001 From: Stefan Boberg Date: Mon, 16 Mar 2026 10:27:24 +0100 Subject: URI decoding, process env, compiler info, httpasio strands, regex route removal (#841) - Percent-decode URIs in ASIO HTTP server to match http.sys CookedUrl behavior, ensuring consistent decoded paths across backends - Add Environment field to CreateProcOptions for passing extra env vars to child processes (Windows: merged into Unicode environment block; Unix: setenv in fork) - Add GetCompilerName() and include it in build options startup logging - Suppress Windows CRT error dialogs in test harness for headless/CI runs - Fix mimalloc package: pass CMAKE_BUILD_TYPE, skip cfuncs test for cross-compile - Add virtual destructor to SentryAssertImpl to fix debug-mode warning - Simplify object store path handling now that URIs arrive pre-decoded - Add URI decoding test coverage for percent-encoded paths and query params - Simplify httpasio request handling by using strands (guarantees no parallel handlers per connection) - Removed deprecated regex-based route matching support - Fix full GC never triggering after cross-toolchain builds: The `gc_state` file stores `system_clock` ticks, but the tick resolution differs between toolchains (nanoseconds on GCC/standard clang, microseconds on UE clang). A nanosecond timestamp misinterpreted as microseconds appears far in the future (~year 58,000), bypassing the staleness check and preventing time-based full GC from ever running. Fixed by also resetting when the stored timestamp is in the future. - Clamp GC countdown display to configured interval: Prevents nonsensical log output (e.g. "Full GC in 492128002h") caused by the above or any other clock anomaly. The clamp applies to both the scheduler log and the status API. --- src/zenstore/gc.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) (limited to 'src/zenstore/gc.cpp') diff --git a/src/zenstore/gc.cpp b/src/zenstore/gc.cpp index b3450b805..f3edf804d 100644 --- a/src/zenstore/gc.cpp +++ b/src/zenstore/gc.cpp @@ -1776,11 +1776,13 @@ GcScheduler::Initialize(const GcSchedulerConfig& Config) m_LastGcTime = GcClock::TimePoint(GcClock::Duration(SchedulerState["LastGcTime"sv].AsInt64())); m_LastGcExpireTime = GcClock::TimePoint(GcClock::Duration(SchedulerState["LastGcExpireTime"].AsInt64(GcClock::Duration::min().count()))); - if (m_LastGcTime + m_Config.Interval < GcClock::Now()) + if (m_LastGcTime > GcClock::Now() || m_LastGcTime + m_Config.Interval < GcClock::Now()) { - // TODO: Trigger GC? + // Reset if the stored timestamp is in the future (e.g. clock resolution mismatch + // between the build that wrote gc_state and this build) or too far in the past. m_LastGcTime = GcClock::Now(); m_LastLightweightGcTime = m_LastGcTime; + m_LastGcExpireTime = GcClock::TimePoint::min(); } m_AttachmentPassIndex = SchedulerState["AttachmentPassIndex"sv].AsUInt8(); } @@ -2084,6 +2086,10 @@ GcScheduler::GetState() const { Result.RemainingTimeUntilFullGc = std::chrono::seconds::zero(); } + else if (Result.RemainingTimeUntilFullGc > Result.Config.Interval) + { + Result.RemainingTimeUntilFullGc = Result.Config.Interval; + } Result.RemainingTimeUntilLightweightGc = Result.Config.LightweightInterval.count() == 0 @@ -2094,6 +2100,10 @@ GcScheduler::GetState() const { Result.RemainingTimeUntilLightweightGc = std::chrono::seconds::zero(); } + else if (Result.RemainingTimeUntilLightweightGc > Result.Config.LightweightInterval) + { + Result.RemainingTimeUntilLightweightGc = Result.Config.LightweightInterval; + } } return Result; @@ -2418,6 +2428,10 @@ GcScheduler::SchedulerThread() { RemainingTimeUntilGc = std::chrono::seconds::zero(); } + else if (RemainingTimeUntilGc > GcInterval) + { + RemainingTimeUntilGc = GcInterval; + } std::chrono::seconds RemainingTimeUntilLightweightGc = LightweightGcInterval.count() == 0 ? std::chrono::seconds::max() @@ -2428,6 +2442,10 @@ GcScheduler::SchedulerThread() { RemainingTimeUntilLightweightGc = std::chrono::seconds::zero(); } + else if (RemainingTimeUntilLightweightGc > LightweightGcInterval) + { + RemainingTimeUntilLightweightGc = LightweightGcInterval; + } // Don't schedule a lightweight GC if a full GC is // due quite soon anyway -- cgit v1.2.3