cdp: remove race between terminate/disconnect

A client that disconnects might get treated as a harsher terminate failure (e.g.
watchdog). This doesn't have a huge impact, but it makes the CI flaky and it
produces more logs than is necessary.

In a terminate state, the driver will now check its inbox to see if this is a
client disconnection.
This commit is contained in:
Karl Seguin committed 2026-09-01 12:11:07 +08:00
1 parent 053ea6aac0
commit a68697921e
2 files changed
+25 -4

No files matched your search

+16 -1
View File
@@ -566,7 +566,10 @@ pub fn activity(self: *const Client) Activity {
// refs to page / session / V8 state; dispatching a
// command that frees that state would UAF on unwind.
// Cherry-pick only Fetch interception responses
const DrainMode = enum { all, sync_wait };
// .terminal - pops only close/disconnect: the connection is going away and
// nothing else may be dispatched, but the peer still gets its
// close reason.
const DrainMode = enum { all, sync_wait, terminal };
// One-shot convenience: create and submit in a single call.
pub fn request(self: *Client, req: Request, owner: ?*Owner) anyerror!void {
@@ -1310,6 +1313,10 @@ fn makeRequest(self: *Client, conn: *http.Connection, transfer: *Transfer) anyer
_ = try self.handles.perform();
}
pub fn drainTerminal(self: *Client) !void {
return self.drainInbox(.terminal);
}
// Drain any client messages the Network thread pushed into our inbox
// and dispatch them via the driver callbacks. Returns
// error.ClientDisconnected if the inbox surfaced a disconnect message,
@@ -1322,6 +1329,7 @@ fn drainInbox(self: *Client, mode: DrainMode) !void {
const msg = switch (mode) {
.all => self.inbox.pop(),
.sync_wait => self.inbox.popIf(allowDuringSyncWait),
.terminal => self.inbox.popIf(isTerminal),
} orelse return;
defer msg.deinit();
@@ -1369,6 +1377,13 @@ fn allowDuringSyncWait(msg: *Inbox.Message) bool {
};
}
fn isTerminal(msg: *Inbox.Message) bool {
return switch (msg.payload) {
.close, .disconnect => true,
.ping, .cdp, .bidi => false,
};
}
fn isFetchInterceptionMethod(method: []const u8) bool {
return std.mem.eql(u8, method, "Fetch.continueRequest") or
std.mem.eql(u8, method, "Fetch.failRequest") or