You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The first-ever Windows run of the workspace suite (windows-check, added in #310) failed leak_canaries::embedding_lifecycle_is_steady_state: vm_churn grew 12,352 bytes over 64 iterations (~193/iter) against the 4,096-byte tolerance. macOS measures ~0 for the same scenario.
Probe data (scratch/windows-leak-probe, counting global allocator, 64 iters after 2 warmups)
vm_create_gc_collect_drop (full collect before drop): ~30/iter
vm_two_per_iter: ~212/iter (2 VMs)
macOS same binary shape: 0-19/iter depending on scenario/order.
What this rules out
NOT introduced by the unresolved external symbol localtime_s #308 sweep: env-path VMs that bypass the new Windows loadlib defaults and make setprogdir a no-op still retain; std::env::current_exe, the lossy conversion, and env::var_os retain zero in isolation; ! substitution adds nothing (37 vs 39).
Retention scales with interned-string volume (default 5.4 paths ~150/iter vs tiny env paths ~39/iter) and is mostly reclaimed by an explicit collectgarbage('collect') before drop.
Counter is layout-based (Layout::size), so allocator size-class rounding cannot explain it; these are real Rust-side allocations not freed by VM drop, on Windows more than macOS, run-to-run variance ~±20%.
Interim
leak_canaries TOLERANCE gets a measured Windows envelope (65,536 bytes/scenario ≈ 1KB/iter headroom) with a pointer to this issue; unix stays at 4,096; the detached tripwire is unchanged everywhere. The envelope still catches #249-class regressions (~29KB/iter → 1.8MB/scenario) by two orders of magnitude.
Next steps
Count allocation COUNT alongside bytes in the canary to see if it's one object or many.
Per-size histogram of unfreed allocations at scenario end (dhat-style) on a Windows box.
Check teardown ordering of interner/registry tables vs heap drop on Windows (timing/order dependence would explain the run-to-run variance).
Investigated by the night-shift (Fable queue run on the prod box). Headline: the retention is platform-neutral, not Windows-specific — reproduced on Linux at ~165 B/iteration (live bytes +10,608 over 64 iterations after warmup), inside this issue's 40-260 envelope. Root cause: the std-file LStream side table outlives VM churn in the embedding lifecycle. Bounded fix + extended leak-canary regression: PR #319.
Activity
changelog: cover #316/#317/#318 in 0.7.1 entry
Merge pull request #318 from ianm199/fix/windows-canary-envelope
ianm199 commentedon Jul 21, 2026
Investigated by the night-shift (Fable queue run on the prod box). Headline: the retention is platform-neutral, not Windows-specific — reproduced on Linux at ~165 B/iteration (live bytes +10,608 over 64 iterations after warmup), inside this issue's 40-260 envelope. Root cause: the std-file LStream side table outlives VM churn in the embedding lifecycle. Bounded fix + extended leak-canary regression: PR #319.
fix(io): per-VM LStream side table — VM churn retention (#317) (#319)
tests: measured Windows envelope for leak-canary byte tolerance (ianm…