summaryrefslogtreecommitdiff
path: root/src/main.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.zig')
-rw-r--r--src/main.zig20
1 files changed, 20 insertions, 0 deletions
diff --git a/src/main.zig b/src/main.zig
index 004d59cb..1fcc2770 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -160,6 +160,26 @@ fn webMain() !void {
}
fn nativeMain(init: std.process.Init) !void {
+ // FIRST, before anything can log or panic. std's start code hands the
+ // debug/log stderr writer the process environ exactly as the kernel laid
+ // it out beside argv, and `std.debug.lockStderr` scans that block once,
+ // lazily, for NO_COLOR and CLICOLOR_FORCE. Lazily is the problem: libc
+ // may have rewritten the block by then. SDL_CreateWindow does, every
+ // time — `Wayland_ShowWindow` unsets XDG_ACTIVATION_TOKEN, and glibc's
+ // unsetenv compacts `environ` in place and leaves a null in the slot the
+ // captured length still counts. `Environ.scan` unwraps that null, so the
+ // FIRST log line or panic in the gui shell panicked inside the scan, and
+ // then the panic handler took the same path and deadlocked on the stderr
+ // lock it was already holding: "attempt to use null value" and a hang,
+ // with no trace and no message of its own. Every SDL_GetError report in
+ // gui.zig was that, which is to say unreachable.
+ //
+ // Locking and immediately unlocking here does the scan while the block is
+ // still the one std was given, and memoizes it. Nothing is written.
+ var stderr_probe: [64]u8 = undefined;
+ _ = std.debug.lockStderr(&stderr_probe);
+ std.debug.unlockStderr();
+
var opts: pardes.Options = .{};
const arena = init.arena.allocator();
const args = try init.minimal.args.toSlice(arena);