8 ms·
In const recv_buffers = try ByteArrayPool.init(gpa, config.connections_max, recv_size); const send_buffers = try ByteArrayPool.init(gpa, config.connect
by matklad 9mo ago
In
const recv_buffers = try ByteArrayPool.init(gpa, config.connections_max, recv_size);
const send_buffers = try ByteArrayPool.init(gpa, config.connections_max, send_size);
if the second try throws, than the memory allocation created by the first try is leaked. Possible fixes:
A) clean up individual allocations on failure:
const recv_buffers = try ByteArrayPool.init(gpa, config.connections_max, recv_size);
errdefer recv_buffers.deinit(gpa);
const send_buffers = try ByteArrayPool.init(gpa, config.connections_max, send_size);
errdefer send_buffers.deinit(gpa);
B) ask the caller to pass in an arena instead of gpa to do bulk cleanup (types & code stays the same, but naming & contract changes):
const recv_buffers = try ByteArrayPool.init(arena, config.connections_max, recv_size);
const send_buffers = try ByteArrayPool.init(arena, config.connections_max, send_size);
C) declare OOMs to be fatal errors
const recv_buffers = ByteArrayPool.init(gpa, config.connections_max, recv_size) catch |err| oom(err);
const send_buffers = ByteArrayPool.init(gpa, config.connections_max, send_size) catch |err| oom(err);
fn oom(_: error.OutOfMemory) noreturn { @panic("oom"); }
You might also be interesting in https://matklad.github.io/2025/12/23/static-allocation-compilers.html https://matklad.github.io/2025/12/23/static-allocation-compi..., it's essentially a complimentary article to what @MatthiasPortzel says here https://news.ycombinator.com/item?id=46423691 https://news.ycombinator.com/item?id=46423691
- nickmonad 9mo agoGotcha. Thanks for clarifying! I guess I wasn't super concerned about the 'try' failing here since this code is squarely in the initialization path, and I want the OOM to bubble up to main() and crash. Although to be fair, 1. Not a great experience to be given a stack trace, could definitely have a nice message there. And 2. If the ConnectionPool init() is (re)used elsewhere outside this overall initialization path, we could run into that leak. The allocation failure that could occur at runtime, post-init, would be here: https://github.com/nickmonad/kv/blob/53e953da752c7f49221c9c433bc05f957f2631b5/src/main.zig#L150-L159 https://github.com/nickmonad/kv/blob/53e953da752c7f49221c9c4... - and the OOM error kicks back an immediate close on the connection to the client.