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.