{"record":{"id":"969d0287d31bfa63","repo":"cross-rs/cross","slug":"container-already-exited-due-to-signal","errorCode":null,"errorMessage":"container already exited due to signal","messagePattern":"container already exited due to signal","errorType":"error_code","errorClass":"eyre::ErrReport","httpStatus":null,"severity":"error","filePath":"src/docker/remote.rs","lineNumber":29,"sourceCode":"use super::engine::Engine;\nuse super::shared::*;\nuse crate::TargetTriple;\nuse crate::config::bool_from_envvar;\nuse crate::errors::Result;\nuse crate::extensions::CommandExt;\nuse crate::file::{self, PathExt, ToUtf8};\nuse crate::rustc::{self, QualifiedToolchain, VersionMetaExt};\nuse crate::shell::MessageInfo;\nuse crate::temp;\n\n// prevent further commands from running if we handled\n// a signal earlier, and the volume is exited.\n// this isn't required, but avoids unnecessary\n// commands while the container is cleaning up.\nmacro_rules! bail_container_exited {\n    () => {{\n        if !ChildContainer::exists_static() {\n            eyre::bail!(\"container already exited due to signal\");\n        }\n    }};\n}\n\n#[track_caller]\nfn subcommand_or_exit(engine: &Engine, cmd: &str) -> Result<Command> {\n    bail_container_exited!();\n    Ok(engine.subcommand(cmd))\n}\n\npub fn posix_parent(path: &str) -> Option<&str> {\n    Path::new(path).parent()?.to_str()\n}\n\nimpl ContainerDataVolume<'_, '_, '_> {\n    // NOTE: `reldir` should be a relative POSIX path to the root directory\n    // on windows, this should be something like `mnt/c`. that is, all paths\n    // inside the container should not have the mount prefix.","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/cross-rs/cross/blob/8c1a8aa4b661711f4b7b6ac07c2e8929ce2f7d27/src/docker/remote.rs#L11-L47","documentation":"The `bail_container_exited!` macro aborts a pending container command when the managed child container has already terminated (e.g. killed by a signal during cleanup). It only bails if `ChildContainer::exists_static()` reports the container no longer exists, preventing commands against a dead container/volume.","triggerScenarios":"Executing a docker subcommand against a cross-managed container after the container process received a signal (SIGINT/SIGTERM) or exited during volume cleanup — detected via the `exists_static` check failing.","commonSituations":"Pressing Ctrl-C while a cross build runs in Docker, CI timeout signals killing the container, or the container crashing mid-operation and subsequent commands racing against its cleanup.","solutions":["Re-run the cross command; the stale container state is cleaned up on the next invocation.","Inspect `docker ps -a` / `docker volume ls` for orphaned cross containers/volumes and remove them.","Avoid sending signals mid-build, or handle graceful shutdown so cleanup completes before exit."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if !ChildContainer::exists_static() {\n    // container gone: skip the command and re-run from a clean state\n}","typeGuard":null,"tryCatchPattern":"match run_in_container(...) {\n    Err(e) if e.to_string().contains(\"container already exited\") => {\n    eprintln!(\"container exited early; cleaning up and retrying\");\n    cleanup();\n}\nErr(e) => return Err(e),\nOk(v) => v,\n}","preventionTips":["Avoid Ctrl-C/SIGTERM mid-build; let cleanup complete.","Increase CI timeouts so builds aren't killed mid-operation.","Periodically prune orphaned cross containers and volumes."],"tags":["docker","container-lifecycle","signal","race"],"backgroundTag":"invalid-state-transition","analyzedSha":"8c1a8aa4b661711f4b7b6ac07c2e8929ce2f7d27","analyzedAt":"2026-09-13T15:10:43.988Z","contentChangedAt":"2026-09-13T15:10:43.988Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}