From fd93334a21907f959018e1b1f5df747a98d186c8 Mon Sep 17 00:00:00 2001 From: salmonik Date: Wed, 4 Nov 2026 01:11:50 +0100 Subject: processes: add timeouts and keep decoding off the runtime --- src/commands/math.rs | 19 ++++++++++++++----- src/commands/qr.rs | 12 ++++++++---- src/commands/utilities.rs | 15 +++++++++++---- src/voice/mod.rs | 36 ++++++++++++++++++++---------------- 4 files changed, 53 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/commands/math.rs b/src/commands/math.rs index 43a7de8..25ddaab 100644 --- a/src/commands/math.rs +++ b/src/commands/math.rs @@ -57,11 +57,20 @@ pub async fn math( return Ok(()); } - let output = tokio::process::Command::new("qalc") - .arg(&equation) - .output() - .await - .map_err(|e| Error::Custom(lang::fmt_math_qalc_err(&e)))?; + let output = match tokio::time::timeout( + std::time::Duration::from_secs(5), + tokio::process::Command::new("qalc") + .arg(&equation) + .output(), + ) + .await + { + Ok(result) => result.map_err(|e| Error::Custom(lang::fmt_math_qalc_err(&e)))?, + Err(_) => { + ctx.say(lang::L_MATH_NO_RESULT).await?; + return Ok(()); + } + }; let result = String::from_utf8_lossy(&output.stdout).trim().to_string(); if result.is_empty() { diff --git a/src/commands/qr.rs b/src/commands/qr.rs index 26232ee..c0b8af0 100644 --- a/src/commands/qr.rs +++ b/src/commands/qr.rs @@ -61,10 +61,14 @@ pub async fn dekodowanie( .await? .bytes() .await?; - let img = image::load_from_memory(&img_data)?; - let gray = img.to_luma8(); - - let decoded = decode_qr_simple(&gray); + // Decoding is CPU-heavy: keep it off the async runtime. + let img_data = img_data.to_vec(); + let decoded = tokio::task::spawn_blocking(move || { + let img = image::load_from_memory(&img_data).ok()?; + let gray = img.to_luma8(); + decode_qr_simple(&gray) + }) + .await?; match decoded { Some(text) => { ctx.say(lang::fmt_qr_decoded(&text)).await?; diff --git a/src/commands/utilities.rs b/src/commands/utilities.rs index bf93491..c26fd0e 100644 --- a/src/commands/utilities.rs +++ b/src/commands/utilities.rs @@ -1,3 +1,5 @@ +use std::time::Duration; + use poise::serenity_prelude as serenity; use tracing::warn; @@ -524,10 +526,15 @@ async fn run_download( } cmd.arg("--").arg(sanitize_yt_url(url)); - let output = cmd - .output() - .await - .map_err(|e| Error::Custom(lang::fmt_ytdlp_err(&e)))?; + let output = match tokio::time::timeout(Duration::from_secs(600), cmd.output()).await { + Ok(result) => result.map_err(|e| Error::Custom(lang::fmt_ytdlp_err(&e)))?, + Err(_) => { + let _ = tokio::fs::remove_dir_all(&dl_dir).await; + ctx.say(lang::fmt_download_failed("download timed out after 10 minutes")) + .await?; + return Ok(()); + } + }; if !output.status.success() { let stderr = String::from_utf8_lossy(&output.stderr); // Keep the full yt-dlp trace in the logs; the user only sees the diff --git a/src/voice/mod.rs b/src/voice/mod.rs index a6baa64..5043508 100644 --- a/src/voice/mod.rs +++ b/src/voice/mod.rs @@ -237,22 +237,26 @@ fn decode_stream(mss: MediaSourceStream) -> Result { /// Download audio via yt-dlp, collect stdout into memory, return the raw bytes. /// Works for both finite media and live streams (yt-dlp handles the difference). pub async fn ytdlp_download(url: &str) -> Result> { - let output = tokio::process::Command::new("yt-dlp") - .args([ - "--ignore-config", - "-f", - "bestaudio", - "-o", - "-", - "--no-playlist", - "--", - url, - ]) - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) - .output() - .await - .map_err(|e| Error::Custom(lang::fmt_voice_ytdlp_launch(&e)))?; + let output = tokio::time::timeout( + Duration::from_secs(600), + tokio::process::Command::new("yt-dlp") + .args([ + "--ignore-config", + "-f", + "bestaudio", + "-o", + "-", + "--no-playlist", + "--", + url, + ]) + .stdout(std::process::Stdio::piped()) + .stderr(std::process::Stdio::piped()) + .output(), + ) + .await + .map_err(|_| Error::Custom("yt-dlp timed out after 10 minutes".into()))? + .map_err(|e| Error::Custom(lang::fmt_voice_ytdlp_launch(&e)))?; if !output.status.success() { let stderr = String::from_utf8_lossy(&output.stderr); -- cgit v1.2.3