mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-08-24 16:11:43 +00:00
libghostty: log to stderr with raw writes, not lockStderr
see the prior commit, but most importantly this makes it so we can replace our IO impl from Threaded.
This commit is contained in:
@@ -3,6 +3,7 @@ const builtin = @import("builtin");
|
||||
const lib = @import("../lib.zig");
|
||||
const CAllocator = lib.alloc.Allocator;
|
||||
const terminal_sys = @import("../sys.zig");
|
||||
const stderr = @import("../../os/stderr.zig");
|
||||
const Result = @import("result.zig").Result;
|
||||
|
||||
/// C: GhosttySysImage
|
||||
@@ -211,8 +212,12 @@ pub fn logFn(
|
||||
/// Formats each message as "[level](scope): message\n". Can be passed
|
||||
/// directly to ghostty_sys_set(GHOSTTY_SYS_OPT_LOG, &ghostty_sys_log_stderr).
|
||||
///
|
||||
/// Uses std.debug.lockStderrWriter for thread-safe, mutex-protected output.
|
||||
/// On freestanding/wasm targets this is a no-op (no stderr available).
|
||||
/// Each log line is emitted with a single raw write to stderr, which keeps
|
||||
/// concurrent log lines from interleaving. We intentionally avoid
|
||||
/// `std.debug.lockStderr` because it routes through `std.Options.debug_io`
|
||||
/// and would keep the entire `std.Io.Threaded` vtable alive in the binary
|
||||
/// (see `os/stderr.zig`). On freestanding/wasm targets this is a no-op
|
||||
/// (no stderr available).
|
||||
pub fn logStderr(
|
||||
_: ?*anyopaque,
|
||||
level: LogLevel,
|
||||
@@ -233,16 +238,32 @@ pub fn logStderr(
|
||||
.debug => "debug",
|
||||
};
|
||||
|
||||
var buffer: [64]u8 = undefined;
|
||||
var locked_stderr = std.debug.lockStderr(&buffer);
|
||||
defer std.debug.unlockStderr();
|
||||
nosuspend {
|
||||
if (scope.len > 0) {
|
||||
locked_stderr.file_writer.interface.print("[{s}]({s}): {s}\n", .{ level_text, scope, message }) catch {};
|
||||
} else {
|
||||
locked_stderr.file_writer.interface.print("[{s}]: {s}\n", .{ level_text, message }) catch {};
|
||||
}
|
||||
// Large enough for a full logFn chunk plus the level/scope prefix.
|
||||
var buffer: [LogEmitter.buffer_size + 128]u8 = undefined;
|
||||
const line: ?[]const u8 = if (scope.len > 0)
|
||||
std.fmt.bufPrint(&buffer, "[{s}]({s}): {s}\n", .{ level_text, scope, message }) catch null
|
||||
else
|
||||
std.fmt.bufPrint(&buffer, "[{s}]: {s}\n", .{ level_text, message }) catch null;
|
||||
if (line) |v| {
|
||||
stderr.write(v);
|
||||
return;
|
||||
}
|
||||
|
||||
// The line didn't fit in our buffer (an embedder called us directly
|
||||
// with a very large message). Fall back to writing the pieces
|
||||
// separately; interleaving with other threads is possible here but
|
||||
// this is a best-effort diagnostic path.
|
||||
stderr.write("[");
|
||||
stderr.write(level_text);
|
||||
stderr.write("]");
|
||||
if (scope.len > 0) {
|
||||
stderr.write("(");
|
||||
stderr.write(scope);
|
||||
stderr.write(")");
|
||||
}
|
||||
stderr.write(": ");
|
||||
stderr.write(message);
|
||||
stderr.write("\n");
|
||||
}
|
||||
|
||||
test "set decode_png with null clears" {
|
||||
|
||||
Reference in New Issue
Block a user