Why is it that using bash and suspending a while loop, the loop stops after being resumed? Short example below.
$ while true; do echo .; sleep 1; done
.
.
^Z
[1]+ Stopped sleep 1
$ fg
sleep 1
$
I'm familiar with signals, and I'm guessing this may be the natural behaviour of bash here, but I'd like to better understand why it behaves in this particular way.
Best Answer
This looks like a bug in several shells, it works as expected with ksh93 and zsh.
Background:
Most shells seem to run the while loop inside the main shell and
Bourne Shell suspends the whole shell if you type ^Z with a non-login shell
bash suspends only the
sleep
and then leaves the while loop in favor of printing a new shell promptdash makes this command unsuspendable
With ksh93, things work very different:
ksh93 does the same, while the command is started the first time, but as
sleep
is a buitin in ksh93, ksh93 has a handler that causes the while loop to fork off the main shell and then suspend at the time when you type ^Z.If you in ksh93 later type
fg
, the forked off child that still runs the loop is continued.You see the main difference when comparing the jobcontrol messages from bash and ksh93:
bash reports:
[1]+ Stopped sleep 1
but ksh93 reports:
^Z[1] + Stopped while true; do echo .; sleep 1; done
zsh behaves similar to ksh93
With both shells, you have a single process (the main shell) as long as you don't type ^Z, and two shell processes after you typed ^Z.