From 556729b88173dae52b076ba3286d75ea6e253259 Mon Sep 17 00:00:00 2001 From: M1 Date: Wed, 18 Mar 2026 13:10:04 +0400 Subject: [PATCH] =?UTF-8?q?fix:=20use=20std::thread=20+=20tokio=20oneshot?= =?UTF-8?q?=20for=20curl=20=E2=80=94=20fully=20decoupled=20from=20tokio=20?= =?UTF-8?q?thread=20pool?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/monitor/src/runner.rs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/apps/monitor/src/runner.rs b/apps/monitor/src/runner.rs index 8d0601e..9e7870d 100644 --- a/apps/monitor/src/runner.rs +++ b/apps/monitor/src/runner.rs @@ -216,22 +216,32 @@ async fn run_curl( } 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 tmp_owned = tmp.clone(); - let result = tokio::task::spawn_blocking(move || { + + let (tx, rx) = tokio::sync::oneshot::channel::<(std::io::Result, Vec)>(); + std::thread::spawn(move || { let status = std::process::Command::new("curl") .args(&args_owned) .stdin(Stdio::null()) .stdout(Stdio::null()) - .stderr(Stdio::piped()) + .stderr(Stdio::null()) .status(); let output = std::fs::read(&tmp_owned).unwrap_or_default(); let _ = std::fs::remove_file(&tmp_owned); - (status, output) - }).await.map_err(|e| format!("spawn_blocking error: {e}"))?; + let _ = tx.send((status, output)); + }); - 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); if exit_code != 0 {