When _not_ in a libcurl callback, deinit the transfer normally

This commit is contained in:
Karl Seguin
2026-02-12 18:29:35 +08:00
parent ed802c0404
commit 0c89dca261
2 changed files with 26 additions and 9 deletions

View File

@@ -252,4 +252,3 @@
testing.expectEqual(XMLHttpRequest.UNSENT, req.readyState); testing.expectEqual(XMLHttpRequest.UNSENT, req.readyState);
}); });
</script> </script>
-->

View File

@@ -111,6 +111,10 @@ config: *const Config,
cdp_client: ?CDPClient = null, cdp_client: ?CDPClient = null,
// keep track of when curl_multi_perform is happening so that we can avoid
// recursive calls into curl (which it will fail)
performing: bool = false,
// libcurl can monitor arbitrary sockets, this lets us use libcurl to poll // libcurl can monitor arbitrary sockets, this lets us use libcurl to poll
// both HTTP data as well as messages from an CDP connection. // both HTTP data as well as messages from an CDP connection.
// Furthermore, we have some tension between blocking scripts and request // Furthermore, we have some tension between blocking scripts and request
@@ -735,7 +739,12 @@ pub const PerformStatus = enum {
fn perform(self: *Client, timeout_ms: c_int) !PerformStatus { fn perform(self: *Client, timeout_ms: c_int) !PerformStatus {
const multi = self.multi; const multi = self.multi;
var running: c_int = undefined; var running: c_int = undefined;
try errorMCheck(c.curl_multi_perform(multi, &running));
{
self.performing = true;
defer self.performing = false;
try errorMCheck(c.curl_multi_perform(multi, &running));
}
// We're potentially going to block for a while until we get data. Process // We're potentially going to block for a while until we get data. Process
// whatever messages we have waiting ahead of time. // whatever messages we have waiting ahead of time.
@@ -1231,13 +1240,22 @@ pub const Transfer = struct {
return; return;
} }
// abort can be called from a libcurl callback, e.g. we get data, we const client = self.client;
// do the header done callback, the client aborts. if (client.performing) {
// libcurl doesn't support re-entrant calls. We can't remove the // We're currently in a curl_multi_perform. We cannot call endTransfer
// handle from the multi during a callback. Instead, we flag this as // as that calls curl_multi_remove_handle, and you can't do that
// aborted, which will signal the callbacks to stop processing the // from a curl callback. Instead, we flag this transfer and all of
// transfer // our callbacks will check for this flag and abort the transfer for
self.aborted = true; // us
self.aborted = true;
return;
}
if (self._handle != null) {
client.endTransfer(self);
}
self.deinit();
} }
pub fn terminate(self: *Transfer) void { pub fn terminate(self: *Transfer) void {