From 97c8ca38325f07eee15d15cf1cae5fd4c7262d6c Mon Sep 17 00:00:00 2001 From: Karl Seguin Date: Tue, 19 May 2026 22:39:48 +0800 Subject: [PATCH] when work is done, don't keep polling, return to process it --- src/Server.zig | 15 --------------- src/browser/HttpClient.zig | 11 ++++++++--- src/cdp/CDP.zig | 4 +--- src/network/Network.zig | 2 +- src/testing.zig | 7 ------- 5 files changed, 10 insertions(+), 29 deletions(-) diff --git a/src/Server.zig b/src/Server.zig index 7214e22b..50c55195 100644 --- a/src/Server.zig +++ b/src/Server.zig @@ -80,18 +80,6 @@ pub fn shutdown(self: *Server) void { } } -// Wait for all in-flight workers to drain. Useful for tests that -// mutate process-global state (e.g. log filters) and need to ensure -// no worker thread is reading that state before mutating it. -pub fn waitIdle(self: *Server) void { - if (@import("builtin").is_test == false) { - @compileError("waitIdle is only meant to be called in tests"); - } - while (self.active_threads.load(.monotonic) > 0) { - std.Thread.sleep(1 * std.time.ns_per_ms); - } -} - pub fn deinit(self: *Server) void { self.shutdown(); @@ -405,9 +393,6 @@ test "Client: http valid handshake" { } test "Client: read invalid websocket message" { - const filter: testing.LogFilter = .init(&.{.cdp}); - defer filter.deinit(); - // 131 = 128 (fin) | 3 where 3 isn't a valid type try assertWebSocketError( 1002, diff --git a/src/browser/HttpClient.zig b/src/browser/HttpClient.zig index 76eab06a..9f849ce5 100644 --- a/src/browser/HttpClient.zig +++ b/src/browser/HttpClient.zig @@ -667,9 +667,14 @@ fn perform(self: *Client, timeout_ms: c_int) anyerror!void { try self.trackConn(conn); } - // Process completions queued from the curl_multi_perform above before - // we potentially block. - _ = try self.processMessages(); + // We just processed completions; their done_callbacks may have + // scheduled microtasks (JS continuations) or queued new transfers. + // Return without polling so the caller (_tick) can run macrotasks + // and re-evaluate. Otherwise we'd sleep on cdp_link_active for up + // to timeout_ms while pending JS work sits idle. + if (try self.processMessages()) { + return; + } // Poll for HTTP I/O. The Network thread will call curl_multi_wakeup // on our multi handle whenever it pushes to our inbox, so we drop diff --git a/src/cdp/CDP.zig b/src/cdp/CDP.zig index 292e0205..c29c91f9 100644 --- a/src/cdp/CDP.zig +++ b/src/cdp/CDP.zig @@ -218,10 +218,8 @@ pub fn onDisconnect(self: *CDP, err: ?anyerror) void { if (WS.errorReply(e)) |close_frame| { self.conn.send(close_frame) catch {}; } - log.warn(.cdp, "CDP disconnect", .{ .err = e }); - } else { - log.info(.cdp, "CDP disconnect", .{}); } + log.info(.cdp, "CDP disconnect", .{ .err = err }); } pub fn sendJSON(self: *CDP, message: anytype) !void { diff --git a/src/network/Network.zig b/src/network/Network.zig index 968e9425..13243d08 100644 --- a/src/network/Network.zig +++ b/src/network/Network.zig @@ -657,7 +657,7 @@ fn processCdpEvents(self: *Network) void { // know it should exit. Drop with notify=true so // on_disconnect surfaces a .disconnect into the inbox. // dropCdp wakes the worker. - lp.log.warn(.cdp, "CDP onData", .{ .err = err }); + lp.log.info(.cdp, "CDP onData", .{ .err = err }); self.dropCdp(link, err, true); any_removed = true; continue; diff --git a/src/testing.zig b/src/testing.zig index 5844071d..3897a06a 100644 --- a/src/testing.zig +++ b/src/testing.zig @@ -761,13 +761,6 @@ pub const LogFilter = struct { /// Restores the log filters to their previous state. pub fn deinit(self: LogFilter) void { - // Worker threads read log.opts.filter_scopes inside log.enabled, - // so we must wait for any in-flight workers to drain before - // writing it — otherwise we race the worker's load on its - // teardown log line. - if (test_cdp_server) |server| { - server.waitIdle(); - } log.opts.filter_scopes = self.old_filter; } };