reliable return code of background process
With bash
, you'll have that guarantee unless you've started another background job (and beware that background jobs can be started with &
but also with coproc
and with process substitution) between the foo &
and the wait
.
POSIX requires that a shell remembers the exit status of at least 25 jobs after they're gone, but bash
remembers a lot more than that.
Now, if you do:
foo & pid=$!
...
bar &
wait "$pid"
You've got no guarantee that bar
will not be given the same pid as foo
(if foo
has terminated by the time bar
starts), so even though it's unlikely, wait "$pid"
may give you the exit status of bar
.
You can reproduce it with:
bash -c '(exit 12; foo) & pid=$!
while : bar & [ "$pid" != "$!" ]; do :;done
wait "$pid"; echo "$?"'
which will (eventually) give you 0
instead of 12
.
To avoid the problem, one way would be to write it as:
{
foo_pid=$!
while ps -p "$foo_pid"
do
ping -c 1 localhost
done
bar &
...
read <&3 ret
if [ "$ret" = 0 ]; then
echo foo was sucessful.
fi
} 3< <(foo > logfile 2>&1; echo "$?")
Related videos on Youtube
Christopher Schmidt
Updated on September 18, 2022Comments
-
Christopher Schmidt almost 2 years
Let's assume the following piece of bash code:
foo > logfile 2>&1 & foo_pid=$! while ps -p$foo_pid do ping -c 1 localhost done wait $foo_pid if [[ $? == 0 ]] then echo "foo success" fi
Is it safe to assume that
$?
indeed contains the return code offoo
and not the return code ofping
? If the answer to that question is: "You cannot assume that." then how can I modify this piece of code to be sure that$?
always contains the return code offoo
? -
Stéphane Chazelas over 10 yearsNo, see my comment to umlaute's answer, and try it for yourself with
bash -c '(exit 12) & sleep 1; wait "$!"; echo "$?"'
-
Stéphane Chazelas over 10 yearsI've never seen
bash
loose track (even after starting thousands of jobs), my example was demonstrating the pid being reused, which may be what you observed in your case as well.