Add more granular assertions

Trying to see how the "ScriptManager.Header buffer" assertion is failing. Either
`headerCallback` is being called multiple times, or the script is corrupt. By
adding a similar assertion in various places, we can hopefully narrow (a) what's
going on and (b) what code is involved.

Also, switched the BufferPool from DoublyLinkedList to SinglyLinkedList. Was
just reviewing this code (to see if the buffer could possibly become corrupt)
and realized this could be switched.
This commit is contained in:
Karl Seguin
2026-02-14 20:01:09 +08:00
parent bbff64bc96
commit 4f81cb9333
2 changed files with 16 additions and 7 deletions

View File

@@ -617,6 +617,7 @@ pub const Script = struct {
node: std.DoublyLinkedList.Node,
script_element: ?*Element.Html.Script,
manager: *ScriptManager,
header_callback_called: bool = false,
const Kind = enum {
module,
@@ -681,7 +682,15 @@ pub const Script = struct {
});
}
lp.assert(self.source.remote.capacity == 0, "ScriptManager.HeaderCallback", .{ .capacity = self.source.remote.capacity });
{
// temp debug, trying to figure out why the next assert sometimes
// fails. Is the buffer just corrupt or is headerCallback really
// being called twice?
lp.assert(self.header_callback_called == false, "ScriptManager.Header recall", .{});
self.header_callback_called = true;
}
lp.assert(self.source.remote.capacity == 0, "ScriptManager.Header buffer", .{ .capacity = self.source.remote.capacity });
var buffer = self.manager.buffer_pool.get();
if (transfer.getContentLength()) |cl| {
try buffer.ensureTotalCapacity(self.manager.allocator, cl);
@@ -894,7 +903,7 @@ const BufferPool = struct {
max_concurrent_transfers: u8,
mem_pool: std.heap.MemoryPool(Container),
const List = std.DoublyLinkedList;
const List = std.SinglyLinkedList;
const Container = struct {
node: List.Node,
@@ -953,7 +962,7 @@ const BufferPool = struct {
b.clearRetainingCapacity();
container.* = .{ .buf = b, .node = .{} };
self.count += 1;
self.available.append(&container.node);
self.available.prepend(&container.node);
}
};

View File

@@ -557,6 +557,7 @@ pub fn fulfillTransfer(self: *Client, transfer: *Transfer, status: u16, headers:
try transfer.fulfill(status, headers, body);
if (!transfer.req.blocking) {
transfer.deinit();
return;
}
transfer._intercept_state = .fulfilled;
}
@@ -1143,7 +1144,7 @@ pub const Transfer = struct {
// against that, so resetting it would allow a 2nd call to headerCallback).
// But it should also be impossible for this to be true. So, I've added
// this assertion to try to narrow down what's going on.
lp.assert(self._header_done_called == false, "Transert.reset header_done_called", .{});
lp.assert(self._header_done_called == false, "Transfer.reset header_done_called", .{});
self._redirecting = false;
self._auth_challenge = null;
@@ -1340,9 +1341,7 @@ pub const Transfer = struct {
// It can be called either on dataCallback or once the request for those
// w/o body.
fn headerDoneCallback(transfer: *Transfer, easy: *c.CURL) !bool {
if (comptime IS_DEBUG) {
std.debug.assert(transfer._header_done_called == false);
}
lp.assert(transfer._header_done_called == false, "Transfer.headerDoneCallback", .{});
defer transfer._header_done_called = true;
try transfer.buildResponseHeader(easy);
@@ -1608,6 +1607,7 @@ pub const Transfer = struct {
}
}
lp.assert(transfer._header_done_called == false, "Transfer.fulfill header_done_called", .{});
if (try req.header_callback(transfer) == false) {
transfer.abort(error.Abort);
return;