6 ms·
Hey matklad! Thanks for hanging out here and commenting on the post. I was hoping you guys would see this and give some feedback based on your work in TigerBeet
by nickmonad 9mo ago
Hey matklad! Thanks for hanging out here and commenting on the post. I was hoping you guys would see this and give some feedback based on your work in TigerBeetle.
You mentioned, "E.g., in OP, memory is leaked on allocation failures." - Can you clarify a bit more about what you mean there?
- matklad 9mo agoIn 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.