From 4569a3338219e7345cb205f8d47527a28faba0d0 Mon Sep 17 00:00:00 2001 From: CJ van den Berg Date: Sat, 7 Mar 2026 19:20:30 +0100 Subject: [PATCH] fix: windows build --- src/main.zig | 23 +++++++++++++++++++++++ src/nightwatch.zig | 15 +++++---------- src/nightwatch_test.zig | 6 +++++- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/main.zig b/src/main.zig index 46de9ed..72f9363 100644 --- a/src/main.zig +++ b/src/main.zig @@ -72,6 +72,27 @@ fn run_posix() void { _ = std.posix.read(sig_pipe[0], &buf) catch {}; } +var win_shutdown = std.atomic.Value(bool).init(false); + +fn win_ctrl_handler(ctrl_type: std.os.windows.DWORD) callconv(.winapi) std.os.windows.BOOL { + _ = ctrl_type; + win_shutdown.store(true, .release); + return std.os.windows.TRUE; +} + +fn run_windows() void { + const SetConsoleCtrlHandler = struct { + extern "kernel32" fn SetConsoleCtrlHandler( + HandlerRoutine: ?*const fn (std.os.windows.DWORD) callconv(.winapi) std.os.windows.BOOL, + Add: std.os.windows.BOOL, + ) callconv(.winapi) std.os.windows.BOOL; + }.SetConsoleCtrlHandler; + _ = SetConsoleCtrlHandler(win_ctrl_handler, std.os.windows.TRUE); + while (!win_shutdown.load(.acquire)) { + std.Thread.sleep(50 * std.time.ns_per_ms); + } +} + fn usage(out: std.fs.File) !void { var buf: [4096]u8 = undefined; var writer = out.writer(&buf); @@ -144,6 +165,8 @@ pub fn main() !void { if (builtin.os.tag == .linux) { try run_linux(&watcher); + } else if (builtin.os.tag == .windows) { + run_windows(); } else if (is_posix) { run_posix(); } diff --git a/src/nightwatch.zig b/src/nightwatch.zig index b031696..f058317 100644 --- a/src/nightwatch.zig +++ b/src/nightwatch.zig @@ -971,16 +971,11 @@ const WindowsBackend = struct { } } - fn add_watch(self: *@This(), allocator: std.mem.Allocator, path: []const u8) (windows.CreateIoCompletionPortError || error{ - InvalidUtf8, - OutOfMemory, - FileWatcherInvalidHandle, - FileWatcherReadDirectoryChangesFailed, - })!void { + fn add_watch(self: *@This(), allocator: std.mem.Allocator, path: []const u8) error{ OutOfMemory, WatchFailed }!void { self.watches_mutex.lock(); defer self.watches_mutex.unlock(); if (self.watches.contains(path)) return; - const path_w = try std.unicode.utf8ToUtf16LeAllocZ(allocator, path); + const path_w = std.unicode.utf8ToUtf16LeAllocZ(allocator, path) catch return error.WatchFailed; defer allocator.free(path_w); const handle = win32.CreateFileW( path_w, @@ -991,16 +986,16 @@ const WindowsBackend = struct { 0x02000000 | 0x40000000, // FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED null, ); - if (handle == windows.INVALID_HANDLE_VALUE) return error.FileWatcherInvalidHandle; + if (handle == windows.INVALID_HANDLE_VALUE) return error.WatchFailed; errdefer _ = win32.CloseHandle(handle); - _ = try windows.CreateIoCompletionPort(handle, self.iocp, @intFromPtr(handle), 0); + _ = windows.CreateIoCompletionPort(handle, self.iocp, @intFromPtr(handle), 0) catch return error.WatchFailed; const buf = try allocator.alignedAlloc(u8, .fromByteUnits(4), buf_size); errdefer allocator.free(buf); const owned_path = try allocator.dupe(u8, path); errdefer allocator.free(owned_path); var overlapped: windows.OVERLAPPED = std.mem.zeroes(windows.OVERLAPPED); if (win32.ReadDirectoryChangesW(handle, buf.ptr, buf_size, 1, notify_filter, null, &overlapped, null) == 0) - return error.FileWatcherReadDirectoryChangesFailed; + return error.WatchFailed; try self.watches.put(allocator, owned_path, .{ .handle = handle, .buf = buf, diff --git a/src/nightwatch_test.zig b/src/nightwatch_test.zig index 0fd8a11..aec0721 100644 --- a/src/nightwatch_test.zig +++ b/src/nightwatch_test.zig @@ -148,7 +148,11 @@ fn makeTempDir(allocator: std.mem.Allocator) ![]u8 { const name = try std.fmt.allocPrint( allocator, "/tmp/nightwatch_test_{d}_{d}", - .{ if (builtin.os.tag == .linux) std.os.linux.getpid() else std.c.getpid(), n }, + .{ switch (builtin.os.tag) { + .linux => std.os.linux.getpid(), + .windows => std.os.windows.GetCurrentProcessId(), + else => std.c.getpid(), + }, n }, ); errdefer allocator.free(name); try std.fs.makeDirAbsolute(name);