fix(#1220): remove default 180s timeout from bash run — no timeout unless explicitly set
This commit is contained in:
parent
4fbe9e4927
commit
280ae23c0c
3 changed files with 46 additions and 29 deletions
|
|
@ -33,9 +33,6 @@ const POLL_INTERVAL: Duration = Duration::from_millis(200);
|
|||
/// Full output always lives in the `.out`/`.err` files.
|
||||
pub const SUMMARY_BYTES: usize = 4096;
|
||||
|
||||
/// Default task timeout.
|
||||
pub const DEFAULT_TIMEOUT_SECS: u64 = 180;
|
||||
|
||||
/// Maximum inline wait (cap on `wait_seconds`).
|
||||
pub const MAX_WAIT_SECS: u64 = 30;
|
||||
|
||||
|
|
@ -136,7 +133,7 @@ pub fn submit_task(cmd: String, timeout_secs: Option<u64>) -> Result<String> {
|
|||
let task = TaskFile {
|
||||
id: id.clone(),
|
||||
cmd,
|
||||
timeout_secs: timeout_secs.unwrap_or(DEFAULT_TIMEOUT_SECS),
|
||||
timeout_secs,
|
||||
status: TaskStatus::Pending,
|
||||
created_at: now_unix(),
|
||||
started_at: None,
|
||||
|
|
@ -308,9 +305,8 @@ async fn run_task(mut task: TaskFile, socket: &Path) {
|
|||
|
||||
let out_path = paths::task_out(&id);
|
||||
let err_path = paths::task_err(&id);
|
||||
let timeout = Duration::from_secs(task.timeout_secs);
|
||||
|
||||
let (timed_out, exit_code) = match exec_cmd(&task.cmd, &out_path, &err_path, timeout).await {
|
||||
let (timed_out, exit_code) = match exec_cmd(&task.cmd, &out_path, &err_path, task.timeout_secs).await {
|
||||
Ok((code, false)) => (false, Some(code)),
|
||||
Ok((_, true)) => {
|
||||
tracing::warn!(id = %id, "bash_runner: task timed out");
|
||||
|
|
@ -341,7 +337,8 @@ async fn run_task(mut task: TaskFile, socket: &Path) {
|
|||
refresh_loose_ends();
|
||||
|
||||
let summary = if timed_out {
|
||||
format!("timed out after {}s", task.timeout_secs)
|
||||
let secs = task.timeout_secs.unwrap_or(0);
|
||||
format!("timed out after {secs}s")
|
||||
} else {
|
||||
format!("exit={}", exit_code.unwrap_or(-1))
|
||||
};
|
||||
|
|
@ -351,11 +348,12 @@ async fn run_task(mut task: TaskFile, socket: &Path) {
|
|||
}
|
||||
|
||||
/// Run `sh -c cmd`, streaming output to files. Returns `(exit_code, timed_out)`.
|
||||
/// `timeout_secs = None` means no timeout — run until natural exit.
|
||||
async fn exec_cmd(
|
||||
cmd: &str,
|
||||
out_path: &Path,
|
||||
err_path: &Path,
|
||||
timeout: Duration,
|
||||
timeout_secs: Option<u64>,
|
||||
) -> Result<(i32, bool)> {
|
||||
use tokio::process::Command;
|
||||
// SAFETY: `nice` is async-signal-safe and modifies only the calling
|
||||
|
|
@ -389,19 +387,31 @@ async fn exec_cmd(
|
|||
err_path,
|
||||
));
|
||||
|
||||
match tokio::time::timeout(timeout, child.wait()).await {
|
||||
Ok(Ok(status)) => {
|
||||
let _ = copy_out.await;
|
||||
let _ = copy_err.await;
|
||||
Ok((status.code().unwrap_or(-1), false))
|
||||
if let Some(secs) = timeout_secs {
|
||||
match tokio::time::timeout(Duration::from_secs(secs), child.wait()).await {
|
||||
Ok(Ok(status)) => {
|
||||
let _ = copy_out.await;
|
||||
let _ = copy_err.await;
|
||||
Ok((status.code().unwrap_or(-1), false))
|
||||
}
|
||||
Ok(Err(e)) => Err(e.into()),
|
||||
Err(_elapsed) => {
|
||||
let _ = child.kill().await;
|
||||
let _ = child.wait().await;
|
||||
let _ = copy_out.await;
|
||||
let _ = copy_err.await;
|
||||
Ok((-1, true))
|
||||
}
|
||||
}
|
||||
Ok(Err(e)) => Err(e.into()),
|
||||
Err(_elapsed) => {
|
||||
let _ = child.kill().await;
|
||||
let _ = child.wait().await;
|
||||
let _ = copy_out.await;
|
||||
let _ = copy_err.await;
|
||||
Ok((-1, true))
|
||||
} else {
|
||||
// No timeout — wait for natural exit.
|
||||
match child.wait().await {
|
||||
Ok(status) => {
|
||||
let _ = copy_out.await;
|
||||
let _ = copy_err.await;
|
||||
Ok((status.code().unwrap_or(-1), false))
|
||||
}
|
||||
Err(e) => Err(e.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue