X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fcloseout.c;h=18a8912dfdbfd16b06e19a5f2ab40bf0a9a8440c;hb=2988c8c21303fdadb3a9efe321870d96f6bdc668;hp=e4093fbd5f9278968fd97aa9eef0f72de169d3fa;hpb=0632e115747ff96e93330c88f536d7354a7ce507;p=gnulib.git
diff --git a/lib/closeout.c b/lib/closeout.c
index e4093fbd5..18a8912df 100644
--- a/lib/closeout.c
+++ b/lib/closeout.c
@@ -1,12 +1,12 @@
-/* Close standard output, exiting with a diagnostic on error.
+/* Close standard output and standard error, exiting with a diagnostic on error.
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2006 Free
- Software Foundation, Inc.
+ Copyright (C) 1998-2002, 2004, 2006, 2008-2010 Free Software Foundation,
+ Inc.
- This program is free software; you can redistribute it and/or modify
+ This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -14,14 +14,14 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+ along with this program. If not, see . */
#include
#include "closeout.h"
#include
+#include
#include
#include
@@ -43,9 +43,48 @@ close_stdout_set_file_name (const char *file)
file_name = file;
}
+static bool ignore_EPIPE /* = false */;
+
+/* Specify the reaction to an EPIPE error during the closing of stdout:
+ - If ignore = true, it shall be ignored.
+ - If ignore = false, it shall evoke a diagnostic, along with a nonzero
+ exit status.
+ The default is ignore = false.
+
+ This setting matters only if the SIGPIPE signal is ignored (i.e. its
+ handler set to SIG_IGN) or blocked. Only particular programs need to
+ temporarily ignore SIGPIPE. If SIGPIPE is ignored or blocked because
+ it was ignored or blocked in the parent process when it created the
+ child process, it usually is a bug in the parent process: It is bad
+ practice to have SIGPIPE ignored or blocked while creating a child
+ process.
+
+ EPIPE occurs when writing to a pipe or socket that has no readers now,
+ when SIGPIPE is ignored or blocked.
+
+ The ignore = false setting is suitable for a scenario where it is normally
+ guaranteed that the pipe writer terminates before the pipe reader. In
+ this case, an EPIPE is an indication of a premature termination of the
+ pipe reader and should lead to a diagnostic and a nonzero exit status.
+
+ The ignore = true setting is suitable for a scenario where you don't know
+ ahead of time whether the pipe writer or the pipe reader will terminate
+ first. In this case, an EPIPE is an indication that the pipe writer can
+ stop doing useless write() calls; this is what close_stdout does anyway.
+ EPIPE is part of the normal pipe/socket shutdown protocol in this case,
+ and should not lead to a diagnostic message. */
+
+void
+close_stdout_set_ignore_EPIPE (bool ignore)
+{
+ ignore_EPIPE = ignore;
+}
+
/* Close standard output. On error, issue a diagnostic and _exit
with status 'exit_failure'.
+ Also close standard error. On error, _exit with status 'exit_failure'.
+
Since close_stdout is commonly registered via 'atexit', POSIX
and the C standard both say that it should not call 'exit',
because the behavior is undefined if 'exit' is called more than
@@ -67,15 +106,19 @@ close_stdout_set_file_name (const char *file)
void
close_stdout (void)
{
- if (close_stream (stdout) != 0)
+ if (close_stream (stdout) != 0
+ && !(ignore_EPIPE && errno == EPIPE))
{
char const *write_error = _("write error");
if (file_name)
- error (0, errno, "%s: %s", quotearg_colon (file_name),
- write_error);
+ error (0, errno, "%s: %s", quotearg_colon (file_name),
+ write_error);
else
- error (0, errno, "%s", write_error);
+ error (0, errno, "%s", write_error);
_exit (exit_failure);
}
+
+ if (close_stream (stderr) != 0)
+ _exit (exit_failure);
}