Re: bash incorrectly handles 'echo' + SIGPIPE under some situations on Linux
On 1/5/16 11:47 AM, c...@cs.toronto.edu wrote: > Bash Version: 4.3 > Patch Level: 11 > Release Status: release > > Description: > > 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. Chet -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/
Re: bash incorrectly handles 'echo' + SIGPIPE under some situations on Linux
> > 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
'official function declaration format' doesn't work if alias defined
I had an alias referring to printf that I wanted to replace with a function. instead of using the function declarator 'function' (or my alias 'sub'), I remembered that the official way was to use: P () { ... } But then ran into problems with the alias taking precedence over the function. Even in the file where the function was defined and exported, I got an error in the export statement about "P" not being a function. I also tried unaliasing it: unalias P >& /dev/null || ((1)) export -f P Pe But still got the "not a function" ... then I realized I had used the official, POSIX format for function declarations, above, but guess it had silently been changed into printf () { ... } by the 'alias'. Sure enough, using the old form: function P () { ... } caused "P" to be defined as a function -- so when it was unaliased and exported, the export statement found the function. I am not sure how one would catch a problem like that other than by make sure the defined function is never the 1st argument on the line (by adding function). Seems like using 'function' is safer. Perhaps the idea of leaving off "function" at the beginning of a function isn't such a good practice? (bash, version 4.3.39) -l