On Thu, May 27, 2010 at 08:21:57PM -0400, Kris Maglione wrote:
> I'm not sure how to describe this bug, but it's affected one of my
> scripts, and those of several of my users. Basically, we've had loops
> dieing when backgrounded programs exit. This is the simplest test case
> I can come up with:

> #!/bin/dash
> {
>       echo foo
>       sleep 1
>       echo foo
>       echo done>/dev/tty
> } | while read p; do
>       ( echo good & ) &
> done
> echo done

> In versions prior to 3800d4934391b, the output would
> "good\ndone\ndone\ngood" (or some permutation thereof depending on
> system load), but from 3800d4934391b on, it's "good\ndone".

> The offending revision:

> [JOBS] Fix dowait signal race

I can reproduce this here. It happens because the child process exit's
SIGCHLD causes an EINTR on the read, which then fails.

While the above testcase works with FreeBSD sh, a similar script with a
trap on CHLD fails in both (and likely also in older dash):

#!/bin/dash
{
        echo foo
        sleep 1
        echo foo
        echo done>/dev/tty
} | { trap : CHLD; while read p; do
        ( echo good & ) &
done }
echo done

Most other shells do not seem to abort a read builtin for a trap. bash
and ksh93 execute the trap right away and then continue the read, while
mksh postpones it until the read is done. POSIX seems vague about it,
but a look at existing scripts suggests that traps should not abort a
read. Executing the trap right away is useful in case it does something
such as exiting, and should be safe given that traps are already invoked
from deeper levels of recursion of the interpreter. If the trap executes
a break, continue or return command outside its boundaries this should
abort the read.

-- 
Jilles Tjoelker
--
To unsubscribe from this list: send the line "unsubscribe dash" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to