fix: use std::thread + tokio oneshot for curl — fully decoupled from tokio thread pool

This commit is contained in:
M1 2026-03-18 13:10:04 +04:00
parent 5e76b2212f
commit 556729b881
1 changed files with 16 additions and 6 deletions

View File

@ -216,22 +216,32 @@ async fn run_curl(
} }
args.push(url.to_string()); args.push(url.to_string());
// Run curl synchronously in a blocking thread — simple and reliable // Run curl in a real OS thread, signal completion via tokio oneshot.
// std::thread detaches completely from tokio's runtime, so a hung curl
// process can't block other monitors. The tokio::time::timeout on the
// oneshot receiver gives us a hard async deadline.
let args_owned = args.clone(); let args_owned = args.clone();
let tmp_owned = tmp.clone(); let tmp_owned = tmp.clone();
let result = tokio::task::spawn_blocking(move || {
let (tx, rx) = tokio::sync::oneshot::channel::<(std::io::Result<std::process::ExitStatus>, Vec<u8>)>();
std::thread::spawn(move || {
let status = std::process::Command::new("curl") let status = std::process::Command::new("curl")
.args(&args_owned) .args(&args_owned)
.stdin(Stdio::null()) .stdin(Stdio::null())
.stdout(Stdio::null()) .stdout(Stdio::null())
.stderr(Stdio::piped()) .stderr(Stdio::null())
.status(); .status();
let output = std::fs::read(&tmp_owned).unwrap_or_default(); let output = std::fs::read(&tmp_owned).unwrap_or_default();
let _ = std::fs::remove_file(&tmp_owned); let _ = std::fs::remove_file(&tmp_owned);
(status, output) let _ = tx.send((status, output));
}).await.map_err(|e| format!("spawn_blocking error: {e}"))?; });
let (status_result, raw_bytes) = result; let (status_result, raw_bytes) = tokio::time::timeout(
std::time::Duration::from_secs_f64(timeout_secs + 2.0),
rx
).await
.map_err(|_| format!("timed out after {:.0}s", timeout_secs))?
.map_err(|_| "curl thread dropped".to_string())?;
let exit_code = status_result.ok().and_then(|s| s.code()).unwrap_or(-1); let exit_code = status_result.ok().and_then(|s| s.code()).unwrap_or(-1);
if exit_code != 0 { if exit_code != 0 {