rust-lang/rust · error
Failed to wait for `as`.
Error message
Failed to wait for `as`.
What it means
This fires in Cranelift codegen's `compile_global_asm` after spawning the system assembler (`as`) with `CG_CLIF_FORCE_GNU_AS` set. The code calls `child.wait().expect("Failed to wait for `as`.")`. This panics if `wait()` fails — which happens when the child process was already reaped (e.g., by a SIGCHLD handler), killed by the OS (OOM killer), or if the system call itself errors (e.g., EINTR without retry, or the PID is invalid).
Source
Thrown at compiler/rustc_codegen_cranelift/src/global_asm.rs:235
// Remove all LLVM style comments
let mut global_asm = global_asm
.lines()
.map(|line| if let Some(index) = line.find("//") { &line[0..index] } else { line })
.collect::<Vec<_>>()
.join("\n");
global_asm.push('\n');
// Assemble `global_asm`
if option_env!("CG_CLIF_FORCE_GNU_AS").is_some() {
let mut child = Command::new(&config.assembler)
.arg("-o")
.arg(&global_asm_object_file)
.stdin(Stdio::piped())
.spawn()
.expect("Failed to spawn `as`.");
child.stdin.take().unwrap().write_all(global_asm.as_bytes()).unwrap();
let status = child.wait().expect("Failed to wait for `as`.");
if !status.success() {
return Err(format!("Failed to assemble `{}`", global_asm));
}
} else {
// Escape { and }
let global_asm = global_asm.replace('{', "{{").replace('}', "}}");
let mut child = Command::new(std::env::current_exe().unwrap())
// Avoid a warning about the jobserver fd not being passed
.env_remove("CARGO_MAKEFLAGS")
.arg("--target")
.arg(&config.target)
.arg("--crate-type")
.arg("staticlib")
.arg("--emit")
.arg("obj")
.arg("-o")
.arg(&global_asm_object_file)View on GitHub (pinned to 7088e4b63a)
Solutions
- Check system memory — `as` may have been OOM-killed. Increase container/host memory limits.
- Retry the build — transient signal/OOM issues are often non-reproducible.
- Remove `CG_CLIF_FORCE_GNU_AS` to use the LLVM-based asm path which doesn't spawn a subprocess.
- If running under a process supervisor that reaps children, disable it or configure it to not reap cg_clif's children.
- Check dmesg/syslog for OOM killer activity: `dmesg | grep -i 'killed process'`.
Example fix
# before (large global_asm + memory pressure → as killed → wait fails) CG_CLIF_FORCE_GNU_AS=1 cargo build # after (remove the flag to avoid spawning `as`) unset CG_CLIF_FORCE_GNU_AS cargo build
Defensive patterns
Strategy: retry
Validate before calling
// Check available memory before building large global_asm blocks:
// In a CI script:
// free -m | awk '/Mem:/ { if ($4 < 512) { echo "Low memory; as may be OOM-killed"; exit 1; } }'
// Or simply avoid CG_CLIF_FORCE_GNU_AS to use the in-process LLVM path. Try / catch
// In a build script, retry on assembler wait failure:
fn assemble_with_retry(asm: &str, n: u32) -> bool {
for _ in 0..n {
let mut child = match Command::new("as").stdin(Stdio::piped()).spawn() {
Ok(c) => c,
Err(_) => return false,
};
if child.wait().is_ok() { return true; }
}
false
} Prevention
- Ensure sufficient memory for assembling large global_asm! blocks.
- Unset CG_CLIF_FORCE_GNU_AS to avoid spawning external 'as'.
- Monitor for OOM kills with 'dmesg' during builds.
- Retry builds that fail transiently due to resource limits.
When it happens
Trigger: The assembler (`as`) was spawned successfully but `wait()` on the child handle fails. This can happen if another part of the process reaps the child (signal handler, threaded runtime), if the OOM killer terminates `as`, or if the process receives a signal that interrupts the wait.
Common situations: Systems under memory pressure where `as` gets OOM-killed during assembly of large `global_asm!` blocks. Process managers or threaded runtimes that install SIGCHLD handlers that race with `wait()`. Rare on normal systems; more common in CI under resource constraints or in containers with strict memory limits.
Related errors
AI-assisted analysis of rust-lang/rust@7088e4b63a (2026-08-10).
Data as JSON: /api/errors/15ca21a45ce8f58b.
Report an issue: GitHub.