curl-rust
curl-rust copied to clipboard
Multi::perform() references a mysterious "info", which doesn't appear to exist – how to get the result for an individual
Quoth https://docs.rs/curl/latest/curl/multi/struct.Multi.html#method.perform at 0.4.44:
If the amount of running handles is changed from the previous call (or is less than the amount of easy handles you’ve added to the multi handle), you know that there is one or more transfers less “running”. You can then call
infoto get information about each individual completed transfer, and that returned info includes Error and more. If an added handle fails very quickly, it may never be counted as a running handle.
and
This function only returns errors etc regarding the whole multi stack. Problems still might have occurred on individual transfers even when this function returns
Ok. Useinfoto figure out how individual transfers did.
And yet!
curl-rust$ git grep '\binfo('
curl-rust$ git grep '\binfo<'
curl-rust$ git grep '\binfo:'
curl-sys/lib.rs: pub fn curl_easy_getinfo(curl: *mut CURL, info: CURLINFO, ...) -> CURLcode;
src/easy/handler.rs: /// More info: <https://curl.se/libcurl/c/CURLOPT_EXPECT_100_TIMEOUT_MS.html>
and rustdoc search unsurprisingly returns nothing as well.
Indeed, it appears I'm actually hitting this in https://github.com/nabijaczleweli/cargo-update/issues/234 where response_code() returns 0, i.e. "no server response code has been received". To that end – how do I get the individual results?
https://curl.se/libcurl/c/curl_multi_perform.html says
This function returns errors regarding the whole multi stack. Problems on individual transfers may have occurred even when this function returns CURLM_OK. Use curl_multi_info_read to figure out how individual transfers did.
which is obviously what the rustdoc is copied from, and indeed
$ git grep curl_multi_info_read
curl-sys/lib.rs: pub fn curl_multi_info_read(
src/multi.rs: let ptr = curl_sys::curl_multi_info_read(self.raw.handle, &mut queue);
which is
/// Read multi stack informationals
///
/// Ask the multi handle if there are any messages/informationals from the
/// individual transfers. Messages may include informationals such as an
/// error code from the transfer or just the fact that a transfer is
/// completed. More details on these should be written down as well.
pub fn messages<F>(&self, mut f: F)
where
F: FnMut(Message),
{
self._messages(&mut f)
}
fn _messages(&self, f: &mut dyn FnMut(Message)) {
let mut queue = 0;
unsafe {
loop {
let ptr = curl_sys::curl_multi_info_read(self.raw.handle, &mut queue);
if ptr.is_null() {
break;
}
f(Message { ptr, _multi: self })
}
}
}
This had also confused me originally when using the multi API. To that end: instead of referencing a mystical "info", please just point to messages() :)