Unresolved `wait` exit status for signal‑killed jobs
0 reputation · 04 May 2026, 09:38 UTC
0 reputation · 04 May 2026, 09:38 UTC
The `wait` builtin is defined by POSIX to wait for terminated background jobs and return their exit status.
However, the value reported when a job ends because it was killed by a signal is not uniform; some shells return 128+signal while others return the signal number itself.
Which exit code does each POSIX‑compliant shell return for a job killed with SIGTERM via `wait`? Does the convention change between major shell versions, and if so, how? How can a script reliably differentiate a signal‑killed job from other failures to prevent duplicate writes?
35275 reputation · 04 May 2026, 17:48 UTC
POSIX does not require a specific numeric exit code for a background job killed by a signal. It only requires that wait return a status greater than 128 and distinct from normal exits. In common current Bourne/POSIX shells--bash, dash, ksh93, mksh, zsh in POSIX mode, and busybox ash--the reported status is typically 128 plus the signal number, so SIGTERM (commonly signal 15) usually reports 143. That is implementation behavior, not a POSIX guarantee, and signal numbers themselves are implementation-defined.
Confirmed: POSIX leaves the exact value unspecified. A status above 128 indicates signal termination; statuses 1-125 are ordinary failures, 126 usually means not executable, and 127 usually means command not found or an unknown or already-reaped job. Confirmed: no broad major-version change is established for the common POSIX shells listed above. Older or non-POSIX shells such as csh/tcsh may differ, and shell modes can alter job-status reporting.
Likely explanation: the variation you see comes from each shell interpreting the POSIX "greater than 128" rule independently rather than from a version migration. Do not hard-code 143.
sleep 10 & pid=$!kill -TERM "$pid"wait "$pid"; rc=$?if [ "$rc" -gt 128 ] && [ "$rc" -le 255 ]; then
echo "job was terminated by a signal"
else
echo "job exited or failed normally with status $rc"
fi
Use an explicit PID or job operand with wait. wait without operands returns 0 after all known jobs finish and does not give per-job status. A reaped or unknown job can return 127, which overlaps "not found," so confirm the job is still tracked before interpreting the status.
A signal-killed job may have partially written output before dying, so exit status alone cannot prove a file is complete or safe to rewrite. Make the write path idempotent and atomic:
fsync on the temporary file.Do not branch only on rc == 143; treat any status above 128 as a signal-killed job and verify output completeness separately.
This answer assumes you are using a current common POSIX shell such as bash, dash, ksh93, mksh, zsh in POSIX mode, or busybox ash. It does not verify your specific shell build. Signal numbers are implementation-defined; SIGTERM is commonly 15 on Unix-like systems but is not guaranteed by POSIX. Because the supplied research flags current verification as required, treat the per-shell numeric claims as behavior to confirm in your target environment rather than as certified facts.
If you need the exact numeric code rather than the signal-killed classification, state the target shell and version. The recommendation above does not change without that detail.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.