Bash Scripting – How to Avoid Busy Waiting Without Sleep Command

bashshell-scriptsleep

I know I can wait on a condition to become true in bash by doing:

while true; do
  test_condition && break
  sleep 1
done

But it creates 1 sub-process at each iteration (sleep). I could avoid them by doing:

while true; do
  test_condition && break
done

But it uses lot of CPU (busy waiting). To avoid sub-processes and busy waiting, I came up with the solution bellow, but I find it ugly:

my_tmp_dir=$(mktemp -d --tmpdir=/tmp)    # Create a unique tmp dir for the fifo.
mkfifo $my_tmp_dir/fifo                  # Create an empty fifo for sleep by read.
exec 3<> $my_tmp_dir/fifo                # Open the fifo for reading and writing.

while true; do
  test_condition && break
  read -t 1 -u 3 var                     # Same as sleep 1, but without sub-process.
done

exec 3<&-                                # Closing the fifo.
rm $my_tmp_dir/fifo; rmdir $my_tmp_dir   # Cleanup, could be done in a trap.

Note: in the general case, I cannot simply use read -t 1 var without the fifo, because it will consume stdin, and will not work if stdin is not a terminal or a pipe.

Can I avoid sub-processes and busy waiting in a more elegant way ?

Best Answer

In newer versions of bash (at least v2), builtins may be loaded (via enable -f filename commandname) at runtime. A number of such loadable builtins is also distributed with the bash sources, and sleep is among them. Availability may differ from OS to OS (and even machine to machine), of course. For example, on openSUSE, these builtins are distributed via the package bash-loadables.