reliable return code of background process

32,607

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 "$?")
Share:
32,607

Related videos on Youtube

Christopher Schmidt
Author by

Christopher Schmidt

Updated on September 18, 2022

Comments

  • Christopher Schmidt
    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 of foo and not the return code of ping? 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 of foo?

  • Stéphane Chazelas
    Stéphane Chazelas over 10 years
    No, see my comment to umlaute's answer, and try it for yourself with bash -c '(exit 12) & sleep 1; wait "$!"; echo "$?"'
  • Stéphane Chazelas
    Stéphane Chazelas over 10 years
    I'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.