From 963f1611fb47f741548dd91e79673e83081352a6 Mon Sep 17 00:00:00 2001 From: Overlord Date: Fri, 7 Aug 2026 23:22:01 +0200 Subject: [PATCH] updated logger: integrate mutex into WriterState (move-safety), fix lock/unlock logic in deinit --- src/logging/log.zig | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/src/logging/log.zig b/src/logging/log.zig index a6a2b4c..ae47a33 100644 --- a/src/logging/log.zig +++ b/src/logging/log.zig @@ -55,20 +55,21 @@ pub const Logger = struct { level: Level = .info, on_error: ErrorCallback = null, - io: std.Io = undefined, - state: *WriterState = undefined, - mutex: std.Io.Mutex = undefined, - allocator: std.mem.Allocator = undefined, + io: std.Io, + state: *WriterState, + allocator: std.mem.Allocator, const Self = @This(); - /// Heap-allocated home for the write buffer and the `File.Writer` - /// built on top of it. `File.Writer` holds a pointer into - /// `buffer`, so both must live at a stable address that survives - /// the `Logger` value itself being copied or moved. + /// Heap-allocated home for the write buffer, the `File.Writer` + /// built on top of it, and the mutex guarding both. `File.Writer` + /// holds a pointer into `buffer`, so all three must live at a + /// stable address that survives the `Logger` value itself being + /// copied or moved. const WriterState = struct { buffer: []u8, + mutex: std.Io.Mutex, writer: std.Io.File.Writer, }; @@ -92,15 +93,16 @@ pub const Logger = struct { const state = try allocator.create(WriterState); state.* = .{ .buffer = buffer, + .mutex = .init, .writer = options.file.writer(options.io, buffer), }; return Self{ .level = options.level, .on_error = options.on_error, + .io = options.io, .state = state, - .mutex = .init, .allocator = allocator, }; } @@ -116,9 +118,12 @@ pub const Logger = struct { /// allocations are freed unconditionally. pub fn deinit(logger: *Self) void { - logger.mutex.lock(logger.io) catch {}; - logger.state.writer.interface.flush() catch {}; - logger.mutex.unlock(logger.io); + if (logger.state.mutex.lock(logger.io)) |_| + { + logger.state.writer.interface.flush() catch {}; + logger.state.mutex.unlock(logger.io); + } + else |_| {} logger.allocator.free(logger.state.buffer); logger.allocator.destroy(logger.state); @@ -143,8 +148,8 @@ pub const Logger = struct { { if (@intFromEnum(level) < @intFromEnum(logger.level)) return; - try logger.mutex.lock(logger.io); - defer logger.mutex.unlock(logger.io); + try logger.state.mutex.lock(logger.io); + defer logger.state.mutex.unlock(logger.io); try logger.state.writer.interface.print(fmt, args); try logger.state.writer.interface.writeByte('\n'); @@ -170,8 +175,8 @@ pub const Logger = struct { /// Returns an error if the underlying writer fails to flush. pub fn flush(logger: *Self) !void { - try logger.mutex.lock(logger.io); - defer logger.mutex.unlock(logger.io); + try logger.state.mutex.lock(logger.io); + defer logger.state.mutex.unlock(logger.io); try logger.state.writer.interface.flush(); }