On 01/20/2012 09:52 AM, Paul Eggert wrote: > Come to think of it, most of the other "error (0, ...)"s are bogus
I took a look and came up with four related patches to fix these. Here's the first one. It fixes the originally-reported bug. I'll send the other three shortly. >From 8bc29f7425509e2cd4068171ea52e40a8294558e Mon Sep 17 00:00:00 2001 From: Paul Eggert <[email protected]> Date: Fri, 20 Jan 2012 22:33:01 -0800 Subject: [PATCH 1/4] grep: don't say "write error" over and over Problem reported by Travis Gummels in <https://bugzilla.redhat.com/show_bug.cgi?id=741452>. * src/main.c (write_error_seen): New static var. (clean_up_stdout): New function. (prline): Do not output 'write error' more than once; exit after the first one. Use the same wording for the diagnostic that close_stdout uses. (main): Clean up with clean_up_stdout, not close_stdout, so that grep doesn't output multiple "write error" diagnostics. * tests/Makefile.am (TESTS): Add epipe. * tests/epipe: New file. --- src/main.c | 17 +++++++++++++++-- tests/Makefile.am | 1 + tests/epipe | 20 ++++++++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100755 tests/epipe diff --git a/src/main.c b/src/main.c index 51135ad..62ce7e3 100644 --- a/src/main.c +++ b/src/main.c @@ -379,6 +379,7 @@ unsigned char eolbyte; /* The input file name, or (if standard input) "-" or a --label argument. */ static char const *filename; static int errseen; +static int write_error_seen; enum directories_type { @@ -425,6 +426,15 @@ suppressible_error (char const *mesg, int errnum) errseen = 1; } +/* If there has already been a write error, don't bother closing + standard output, as that might elicit a duplicate diagnostic. */ +static void +clean_up_stdout (void) +{ + if (! write_error_seen) + close_stdout (); +} + /* Convert STR to a positive integer, storing the result in *OUT. STR must be a valid context length argument; report an error if it isn't. */ @@ -881,7 +891,10 @@ prline (char const *beg, char const *lim, int sep) fwrite (beg, 1, lim - beg, stdout); if (ferror (stdout)) - error (0, errno, _("writing output")); + { + write_error_seen = 1; + error (EXIT_TROUBLE, 0, _("write error")); + } lastout = lim; @@ -1845,7 +1858,7 @@ main (int argc, char **argv) #endif exit_failure = EXIT_TROUBLE; - atexit (close_stdout); + atexit (clean_up_stdout); last_recursive = 0; prepended = prepend_default_options (getenv ("GREP_OPTIONS"), &argc, &argv); diff --git a/tests/Makefile.am b/tests/Makefile.am index 77b670b..571bd1b 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -49,6 +49,7 @@ TESTS = \ dfa-heap-overrun \ dfaexec-multibyte \ empty \ + epipe \ equiv-classes \ ere \ euc-mb \ diff --git a/tests/epipe b/tests/epipe new file mode 100755 index 0000000..336d994 --- /dev/null +++ b/tests/epipe @@ -0,0 +1,20 @@ +#!/bin/sh +# Check that a write failure with errno == EPIPE +# doesn't cause grep to issue multiple "write error" diagnostics. + +. "${srcdir=.}/init.sh"; path_prepend_ ../src + +if + ( + while :; do echo x; done | + (trap '' PIPE; exec grep x 2>&3) | + : + ) 3>&1 | ( + read line1 && echo >&2 "$line1" && + read line2 && echo >&2 "$line2" + ) +then fail=1 +else fail=0 +fi + +Exit $fail -- 1.7.6.5
