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 (viaenable -f filename commandname
) at runtime. A number of such loadable builtins is also distributed with the bash sources, andsleep
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 packagebash-loadables
.