bashshelltimeoutwaitpid

Using sleep and wait -n to implement simple timeout in bash, race condition or not?


If I do this in a bash script:

sleep 10 &
sleep_pid=$!
some_command &
wait -n
cmd_pid=$!

if kill -0 $sleep_pid 2> /dev/null; then
    # all ok
    kill $sleep_pid
else
    # some_command hung
    ...code to log diagnostics and then kill -9 $cmd_pid...
fi

where some_command is something that should be quick but can hang due to rare errors.

Is there then a risk that some_command can be done and cleaned up before "wait -n" starts, so there is only the sleep to wait for? Or does the '&' after one command guarantee that the shell won't call waitpid() on it until the next line of input has been handled?

It works in interactive shells. If you do:

sleep 10 &
sleep 0 &
wait -n

then the "wait -n" returns right away even if you wait a couple of seconds before running it. But I'm not sure if it can be trusted for non-interactive shells?

EDIT: Clarifying need for diagnostics + some grammar.


Solution

  • As @CharlesDuffy pointed out in comments, the answer is no, there is no race (provided it is run in a non-interactive shell).

    Also there is no need (in non-interactive shells) to make sure the wait comes directly after the command, as non-interactive shells don't do automatic reaping of children.

    But I guess one should wrap this in a sub-shell, so "wait -n" won't return early due to some previously started unrelated background job.