From e56a4f6259d8ce86b4cc240651917ca209854a1a Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Thu, 2 Jul 2026 11:19:53 +0200 Subject: [PATCH 1/2] use getrandom syscall for std.crypto.random MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit std.crypto.random's default backend mmaps a thread-local 528-byte state page on first use and never unmaps it — there is no thread-exit hook. With one detached thread per CDP connection (Server.handleConnection), that leaks one resident page per connection (uuidv4 in Page.getOrCreateOrigin touches it), ~4KB/conn of unbounded RSS growth. Route every std.crypto.random call to the getrandom syscall instead. .crypto_always_getrandom = true, --- src/main.zig | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main.zig b/src/main.zig index 439c3a36b..318db0f98 100644 --- a/src/main.zig +++ b/src/main.zig @@ -27,6 +27,16 @@ const Config = lp.Config; const SigHandler = @import("Sighandler.zig"); pub const panic = lp.crash_handler.panic; +pub const std_options: std.Options = .{ + // std.crypto.random's default backend mmaps a thread-local 528-byte state + // page on first use and never unmaps it — there is no thread-exit hook. + // With one detached thread per CDP connection (Server.handleConnection), + // that leaks one resident page per connection (uuidv4 in + // Page.getOrCreateOrigin touches it), ~4KB/conn of unbounded RSS growth. + // Route every std.crypto.random call to the getrandom syscall instead. + .crypto_always_getrandom = true, +}; + pub fn main() !void { // allocator // - in Debug mode we use the General Purpose Allocator to detect memory leaks From 37a7f034c84de59b59a28fddf0757673e6e5a244 Mon Sep 17 00:00:00 2001 From: Pierre Tachoire Date: Thu, 2 Jul 2026 11:23:45 +0200 Subject: [PATCH 2/2] use writerStreaming in log --- src/log.zig | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/log.zig b/src/log.zig index f9b7a793b..20ac2fa11 100644 --- a/src/log.zig +++ b/src/log.zig @@ -172,7 +172,11 @@ pub fn log(scope: Scope, level: Level, msg: []const u8, data: anytype) void { var buf: [4096]u8 = undefined; var stderr = std.fs.File.stderr(); - var writer = stderr.writer(&buf); + // writerStreaming, not writer: the default positional mode starts each + // fresh Writer at offset 0, so when stderr is redirected to a regular file + // every log line overwrites the previous one. Streaming writes at the fd + // offset, which is what append-style logging needs. + var writer = stderr.writerStreaming(&buf); logTo(scope, level, msg, data, &writer.interface) catch |log_err| { std.debug.print("$time={d} $level=fatal $scope={s} $msg=\"log err\" err={s} log_msg=\"{s}\"\n", .{ timestamp(.clock), @errorName(log_err), @tagName(scope), msg });