-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 According to Bruno Haible on 3/3/2009 5:37 PM: > Eric Blake wrote: >> When running test-closein.sh, I'm getting spurious output on Darwin: >> >> cat: standard output: Bad file descriptor >> PASS: test-closein.sh > > How to reproduce?
$ uname -r 8.11.0 corresponds to Mac OS X 10.4.11 > On Darwin 7 and 9 (MacOS X 10.3.x and 10.9.x) I reproduce an > error from > $ cat foo | : > or > $ { sleep 1; cat foo; } | : > only if I previously issued the command > $ trap '' SIGPIPE I made sure that SIGPIPE is not ignored when I log in (since POSIX states that shells are not allowed to re-enable a signal that they inherited in the ignored state). My shell is bash 3.2.39. I can post ktrace/kdump output, if you are interested (although it gets rather long). $ seq 10000 | : $ (trap '' PIPE; seq 10000 | :) seq: write error: Broken pipe But the failure I'm seeing is EBADF, not EPIPE: $ cat foo | : cat: standard output: Bad file descriptor and unaffected by SIGPIPE: $ (trap '' PIPE; cat foo | :) cat: standard output: Bad file descriptor >> -# Test for lack of error on pipe >> -cat ${p}in.tmp | ./test-closein${EXEEXT} || exit 1 >> +# Test for lack of error on pipe. Ignore any EPIPE failures from cat. >> +cat ${p}in.tmp 2>/dev/null | ./test-closein${EXEEXT} || exit 1 > > Changes like this reduce the reliability and debuggability of shell scripts, > because you throw away *all* kinds of error output. If there was a typo > in the word 'cat', or the program did not find its shared libraries, or > is symlinks to an /etc/alternatives/cat which is misconfigured, or similar > general errors, we *want* to see the error message. We are testing how ./test-closein behaves when its stdin is a pipe. We don't care what happened on the other end of the pipe, since test-closein doesn't even validate what it read. All we care about is that test-closein doesn't complain about failure to seek on stdin, and doesn't complain when closing stdin. > > Is the situation where SIGPIPE is ignored a recurrent one? It looks like the bug is worse than SIGPIPE - it really is the Darwin kernel closing the read end of the pipe, such that the write end gets EBADF instead of EPIPE or SIGPIPE. > I would prefer to add a > catch-all clause to the beginning of all tests which use pipes: > > #!/bin/sh > if trap | grep "^trap -- ['\"]['\"] SIGPIPE\$" > /dev/null; then > echo "Skipping test: SIGPIPE is ignored" > exit 77 > fi That won't necessarily help - a shell that inherits an ignored SIGPIPE, rather than having an explicitly user-ignored situation, is under no obligation to report that fact during 'trap -p'. And you can often write tests in such a way that you can guarantee the reader will consume all input until the writer has completed, rather than completing early, to avoid the issue of whether SIGPIPE is ignored. - -- Don't work too hard, make some time for fun as well! Eric Blake e...@byu.net -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (Cygwin) Comment: Public key at home.comcast.net/~ericblake/eblake.gpg Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iEYEARECAAYFAkmt3eEACgkQ84KuGfSFAYChugCeP6xsbWi7/kigpIx4tXv2tWJP ESgAoKhrga8qqEh/Nqkpctpta/6cB0rq =yrN3 -----END PGP SIGNATURE-----