Why does a while loop stop after being suspended?
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 prompt
dash 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.
I wrote one of the co-authors of Bash about the issue, and here is his reply:
It's not really a bug, but it is certainly a caveat.
The idea here is that you suspend processes, which are a different unit of granularity than shell commands. When a process is suspended, it returns to the shell (with a non-zero status, which has consequences when you, say, stop a process that's the loop test), which has a choice: it can break out of or continue the loop, leaving the stopped process behind. Bash chooses -- and has always chosen -- to break out of loops when a job is stopped. Continuing the loop is rarely what you want.
Some other shells do things like fork a copy of the shell when a process gets suspended due to SIGTSTP, and stop that process. Bash hasn't ever done that -- it seems more complicated than the benefit warrants -- but if someone wants to submit that code as a patch, I'd take a look at incorporating the changes.
So if anyone wants to submit a patch, use the email addresses found in the man pages.