in src/plugin/plugin_curl.rs [239:335]
fn hook_curl_multi_exec(&self) -> (Box<BeforeExecuteHook>, Box<AfterExecuteHook>) {
(
Box::new(|request_id, execute_data| {
validate_num_args(execute_data, 1)?;
let multi_id = Self::get_resource_id(execute_data)?;
let is_exec = CURL_MULTI_INFO_MAP.with(|map| {
let mut map = map.borrow_mut();
let Some(multi_info) = map.get_mut(&multi_id) else {
debug!(multi_id, "curl multi info is missing, maybe hasn't handles");
return Ok(false);
};
debug!(multi_id, "curl multi handles count: {}", multi_info.curl_handles.len());
if multi_info.curl_handles.is_empty() {
return Ok(false);
}
if multi_info.exec_spans.is_some() {
return Ok(true);
}
let mut curl_infos = Vec::with_capacity(multi_info.curl_handles.len());
for (cid, ch) in &multi_info.curl_handles {
curl_infos.push( (*cid, ch.clone(), Self::get_curl_info(*cid, ch.clone())?));
}
curl_infos.sort_by(|(_, _, i1), (_, _, i2)| i2.raw_url.cmp(&i1.raw_url));
let mut exec_spans = Vec::with_capacity(curl_infos.len());
for (cid, ch, info) in curl_infos {
let span = Self::create_exit_span(request_id, &info)?;
if info.is_http {
Self::inject_sw_header(request_id, ch, &info)?;
}
let span = span.prepare_for_async();
debug!(multi_id, operation_name = ?&span.span_object().operation_name, "create exit span");
exec_spans.push((cid, span));
}
multi_info.exec_spans = Some(exec_spans);
Ok::<_, crate::Error>(true)
})?;
Ok(Box::new(is_exec))
}),
Box::new(move |_, is_exec, execute_data, return_value| {
let is_exec = is_exec.downcast::<bool>().unwrap();
if !*is_exec {
return Ok(());
}
if return_value.as_long() != Some(CURLM_OK) {
return Ok(());
}
let still_running = execute_data.get_parameter(1);
if still_running
.as_z_ref()
.map(|r| r.val())
.and_then(|val| val.as_long())
!= Some(0)
{
return Ok(());
}
let multi_id = Self::get_resource_id(execute_data)?;
debug!(multi_id, "curl multi exec has finished");
CURL_MULTI_INFO_MAP.with(|map| {
let Some(mut info) = map.borrow_mut().remove(&multi_id) else {
warn!(multi_id, "curl multi info is missing after finished");
return Ok(());
};
let Some(mut spans) = info.exec_spans else {
warn!(multi_id, "curl multi spans is missing after finished");
return Ok(());
};
debug!(multi_id, "curl multi spans count: {}", spans.len());
loop {
let Some((cid, mut span)) = spans.pop() else {
break;
};
let Some(ch) = info.curl_handles.remove(&cid) else {
continue;
};
Self::finish_exit_span(&mut span, &ch)?;
}
Ok::<_, crate::Error>(())
})?;
Ok(())
}),
)
}