Introduce deinitIfLive utility and integrate enhanced memory management

This commit is contained in:
2026-08-02 22:59:02 +02:00
parent b1bdfccd1e
commit d70a051a57
3 changed files with 62 additions and 10 deletions

View File

@@ -1,3 +1,8 @@
//! Entry point for the zocket daemon.
//!
//! Handles allocator selection (debug-checked vs. release), CLI argument
//! parsing, and configuration path resolution before handing off to `run`.
const zocket = @import("zocket");
const std = @import("std");
@@ -7,6 +12,14 @@ const options = @import("build_options");
const args = zocket.deps.args;
// TODO: switch vars/consts/params to snake_case
/// Resolves the config path, then delegates to `run`.
///
/// Allocator strategy:
/// - Debug builds use `DebugAllocator`, which tracks every allocation and
/// panics/exits on leaks or double-frees.
/// - Release builds use `c_allocator` for C ABI interop.
pub fn main(init: std.process.Init) !void
{
const debug = builtin.mode == .Debug;
@@ -21,10 +34,13 @@ pub fn main(init: std.process.Init) !void
const allocator = if (debug) gpa.allocator() else std.heap.c_allocator;
var tmpArena = std.heap.ArenaAllocator.init(std.heap.c_allocator);
const tmpAllocator = tmpArena.allocator();
var tmp_arena = std.heap.ArenaAllocator.init(allocator);
var arena_live = true;
var parser = try args.ArgumentParser.init(tmpAllocator, .{
const tmp_allocator = tmp_arena.allocator();
errdefer zocket.memory.deinitIfLive(&tmp_arena, &arena_live);
var parser = try args.ArgumentParser.init(tmp_allocator, .{
.name = "zocket",
.version = options.version,
.description = "A lightweight Zig WebSocket server and mesh routing daemon.",
@@ -39,23 +55,30 @@ pub fn main(init: std.process.Init) !void
const path = if (debug) path:
{
const tmpPath = result.getString("path") orelse "config/config.toml";
break :path try allocator.dupe(u8, tmpPath);
const tmp_path = result.getString("path") orelse "config/config.toml";
break :path try allocator.dupe(u8, tmp_path);
}
else path:
{
const tmpPath = result.getString("path") orelse blk: {
const exe = try std.process.executableDirPathAlloc(io, tmpAllocator);
break :blk try std.Io.Dir.path.join(tmpAllocator, &.{ exe, "config/config.toml" });
const tmp_path = result.getString("path") orelse blk: {
const exe = try std.process.executableDirPathAlloc(io, tmp_allocator);
break :blk try std.Io.Dir.path.join(tmp_allocator, &.{ exe, "config/config.toml" });
};
break :path try allocator.dupe(u8, tmpPath);
break :path try allocator.dupe(u8, tmp_path);
};
tmpArena.deinit();
zocket.memory.deinitIfLive(&tmp_arena, &arena_live);
try run(io, allocator, path);
}
/// Loads and parses the configuration file at `path`, then hands off to
/// the rest of the application.
///
/// Owns `path` and frees it once it's no longer needed; Callers must not free `path` themselves!
///
/// On parse failure, logs a human-readable reason and terminates the
/// process immediately via `std.process.exit`.
fn run(io: std.Io, allocator: std.mem.Allocator, path: []const u8) !void
{
const parsed = zocket.config.parse(io, allocator, path) catch |err|