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 }); diff --git a/src/main.zig b/src/main.zig index 3541e4c41..ca0b75325 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