Differences between revisions 2 and 3
Revision 2 as of 2011-09-12 22:36:07
Size: 1164
Editor: HectorOron
Comment: Comment on code inefficiency and point to Process Management page
Revision 3 as of 2011-09-12 23:03:28
Size: 1489
Editor: GreyCat
Comment:
Deletions are marked like this. Additions are marked like this.
Line 3: Line 3:
There are numerous ways to do this, but all of them are either limited by the available tools.
I have come up with the following solution.
There are numerous ways to do this, but all of them are either limited by the available tools.  I have come up with the following solutions.
Line 6: Line 5:
If you want to wait for ''all'' your children, simply call `wait` with no arguments.

If you just want to wait for some, but not all, and don't care about their exit status, you can call `wait` with multiple PIDs:
{{{
wait $pid1 $pid2
}}}

If you need to know whether the children succeeded or failed, then perhaps:
Line 41: Line 48:
Looping through {{{kill -0}}} can be very unefficient. Looping through {{{kill -0}}} can be very inefficient.

How do I wait for several spawned processes?

There are numerous ways to do this, but all of them are either limited by the available tools. I have come up with the following solutions.

If you want to wait for all your children, simply call wait with no arguments.

If you just want to wait for some, but not all, and don't care about their exit status, you can call wait with multiple PIDs:

wait $pid1 $pid2

If you need to know whether the children succeeded or failed, then perhaps:

waitall() { # PID...
  ## Wait for children to exit and indicate whether all exited with 0 status.
  local errors=0
  while :; do
    debug "Processes remaining: $*"
    for pid in "$@"; do
      shift
      if kill -0 "$pid" 2>/dev/null; then
        debug "$pid is still alive."
        set -- "$@" "$pid"
      elif wait "$pid"; then
        debug "$pid exited with zero exit status."
      else
        debug "$pid exited with non-zero exit status."
        ((++errors))
      fi
    done
    (("$#" > 0)) || break
    # TODO: how to interrupt this sleep when a child terminates?
    sleep ${WAITALL_DELAY:-1}
   done
  ((errors == 0))
}

debug() { echo "DEBUG: $*" >&2; }

pids=""
for t in 3 5 4; do
  sleep "$t" &
  pids="$pids $!"
done
waitall $pids

Looping through kill -0 can be very inefficient.

More useful information might be found at Process Management page.

BashFAQ/108 (last edited 2011-09-12 23:03:28 by GreyCat)