> > If Bash writes to stdout with the built in echo and gets a SIGPIPE,
> > it can incorrectly buffer and then repeat this would-have-been output
> > in at least $(...) things invoked in a cleanup function and in fact
> > in some other contexts as well. To see this in action, create the
> > following script as /tmp/repro:
> > 
> >     #!/bin/bash
> >     function cleanup() {
> >             r1=$(/bin/echo one)
> >             r2=$(/bin/echo two)
> >             echo $r1 '!' $r2 1>&2
> >             #echo $r1 '!' $r2 >>/tmp/logout
> >     }
> >     trap cleanup EXIT
> >     sleep 1
> >     echo final
> > 
> > Run it as '/tmp/repro | false'. The output produced is the clearly
> > incorrect:
> >     $ /tmp/repro | false
> >     final
> >     one final ! two final
> 
> Thanks for the report.  This appears to be easily reproducible on Linux.
> 
> Adding a call to fpurge() to discard buffered output on stdout before
> dup2() replaces file descriptor 1 in the child process fixes it.

 Note that the problem isn't only in the children; the parent process
itself has a problem too, as the 'final' by itself should not be printed
either (and comes entirely from the parent).

$ cat repro2
#!/bin/bash
function cleanup() {
        echo end 1>&2
}
trap cleanup EXIT
sleep 1
echo final

$ ./repro2 | false
final
end

 Strace on Linux confirms that this only fork()s to do the sleep; the
entire sequence from returning from sleep through the end happens in the
main Bash process.

        - cks

Reply via email to