Introduce deinitIfLive utility and integrate enhanced memory management
This commit is contained in:
43
src/main.zig
43
src/main.zig
@@ -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|
|
||||
|
||||
Reference in New Issue
Block a user