fix: p attach on dead/unknown sessions

This commit is contained in:
2026-05-21 20:46:40 +02:00
parent 37af090a8f
commit 5a0021c6a3

View File

@@ -11,20 +11,23 @@ pub fn execute(job_id: &str) -> Result<()> {
let cfg = config::load()?; let cfg = config::load()?;
let job = db::find(job_id)?.with_context(|| format!("job '{}' not found", job_id))?; let job = db::find(job_id)?.with_context(|| format!("job '{}' not found", job_id))?;
if job.status != JobStatus::Running { // Allow attach on Running (normal) and Unknown (worker was temporarily
anyhow::bail!( // unreachable — the job may still be live).
match job.status {
JobStatus::Running | JobStatus::Unknown => {}
_ => anyhow::bail!(
"job {} is not running (status: {})\n\ "job {} is not running (status: {})\n\
use 'p logs {}' to view its output", use 'p logs {}' to view its output",
job.short_id(), job.short_id(),
job.status.as_str(), job.status.as_str(),
job.short_id(), job.short_id(),
); ),
} }
let worker = cfg.resolve_worker(Some(&job.worker))?.clone(); let worker = cfg.resolve_worker(Some(&job.worker))?.clone();
let session = format!("p-{}", job.short_id()); let session = format!("p-{}", job.short_id());
let sid = job.short_id().to_string(); let sid = job.short_id().to_string();
{ {
let sid = sid.clone(); let sid = sid.clone();
ctrlc::set_handler(move || { ctrlc::set_handler(move || {
@@ -36,9 +39,30 @@ pub fn execute(job_id: &str) -> Result<()> {
.ok(); .ok();
} }
ssh::run_interactive(&worker, &format!("tmux attach -t '{}'", session))?; let attach_status = ssh::run_interactive(&worker, &format!("tmux attach -t '{}'", session))?;
// If tmux exited non-zero the session doesn't exist on the worker.
if !attach_status.success() {
let exit_code = ssh::read_job_exitcode(&worker, &job.id);
if exit_code.is_none() {
// No exit code either — the job was lost without completing
// (e.g. worker restarted, tmux server killed).
eprintln!(
"error: tmux session for job {} no longer exists on '{}'.",
sid, worker.name
);
eprintln!("The job was likely interrupted (worker restart or tmux server exit).");
eprintln!("Use 'p logs {}' to see whatever output was captured.", sid);
db::save(&Job {
status: JobStatus::Unknown,
..job
})?;
return Ok(());
}
// Exit code exists — job finished cleanly but the session was already
// cleaned up. Fall through to normal reconciliation.
}
// Same reconciliation logic as the run command.
let exit_code = ssh::read_job_exitcode(&worker, &job.id); let exit_code = ssh::read_job_exitcode(&worker, &job.id);
let now = Utc::now().timestamp(); let now = Utc::now().timestamp();