> > 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