[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: tee logs no output if stdout is closed
From: |
Bruno Haible |
Subject: |
Re: tee logs no output if stdout is closed |
Date: |
Tue, 1 Jul 2008 02:26:16 +0200 |
User-agent: |
KMail/1.5.4 |
Andreas Schwab wrote:
> > How about adding an option '-p' to 'tee', that causes it to ignore SIGPIPE
> > while writing to stdout?
>
> Just add a trap '' SIGPIPE before starting tee.
Thanks, this does half of the trick: Each 'tee' invocation then writes
the complete stdin contents to the log file. But each 'tee' invocation also
complains:
tee: standard output: Broken pipe
tee: write error
tee: standard output: Broken pipe
tee: write error
...
I don't see any better solution than putting support for this into 'tee'
itself. Jim, here's a patch.
From 9813ded2983b0a7f276dc249e68a246bf9c1686a Mon Sep 17 00:00:00 2001
From: Bruno Haible <address@hidden>
Date: Tue, 1 Jul 2008 02:22:10 +0200
Subject: [PATCH] New tee option -p.
* src/tee.c (ignore_sigpipe): New variable.
(long_options): Add option -p.
(usage): Document option -p.
(main): Handle option -p.
(tee_files): When option -p is specified, ignore SIGPIPE write errors.
* doc/coreutils.texi (tee invocation): Document option -p.
---
doc/coreutils.texi | 11 +++++++++++
src/tee.c | 38 ++++++++++++++++++++++++++++++++++----
2 files changed, 45 insertions(+), 4 deletions(-)
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index 155ba8d..c5d7745 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -11341,6 +11341,17 @@ them.
@opindex --ignore-interrupts
Ignore interrupt signals.
address@hidden -p
address@hidden --ignore-sigpipe
address@hidden -p
address@hidden --ignore-sigpipe
+Ignore failed writes to pipes with no readers. By default, when standard
+output or one of the given files refers to a pipe with no reading processes,
+the operating system will kill the @command{tee} process with signal
address@hidden, thus terminating the output to the other files. When the
+option @samp{-p} is specified, the @command{tee} process will continue
+writing to the other specified files.
+
@end table
The @command{tee} command is useful when you happen to be transferring a large
diff --git a/src/tee.c b/src/tee.c
index 4e46aab..85f4529 100644
--- a/src/tee.c
+++ b/src/tee.c
@@ -41,10 +41,14 @@ static bool append;
/* If true, ignore interrupts. */
static bool ignore_interrupts;
+/* If true, ignore failed writes to pipes with no readers. */
+static bool ignore_sigpipe;
+
static struct option const long_options[] =
{
{"append", no_argument, NULL, 'a'},
{"ignore-interrupts", no_argument, NULL, 'i'},
+ {"ignore-sigpipe", no_argument, NULL, 'p'},
{GETOPT_HELP_OPTION_DECL},
{GETOPT_VERSION_OPTION_DECL},
{NULL, 0, NULL, 0}
@@ -64,6 +68,7 @@ Copy standard input to each FILE, and also to standard
output.\n\
\n\
-a, --append append to the given FILEs, do not overwrite\n\
-i, --ignore-interrupts ignore interrupt signals\n\
+ -p, --ignore-sigpipe ignore failed writes to pipes with no readers\n\
"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);
fputs (VERSION_OPTION_DESCRIPTION, stdout);
@@ -93,7 +98,7 @@ main (int argc, char **argv)
append = false;
ignore_interrupts = false;
- while ((optc = getopt_long (argc, argv, "ai", long_options, NULL)) != -1)
+ while ((optc = getopt_long (argc, argv, "aip", long_options, NULL)) != -1)
{
switch (optc)
{
@@ -105,6 +110,10 @@ main (int argc, char **argv)
ignore_interrupts = true;
break;
+ case 'p':
+ ignore_sigpipe = true;
+ break;
+
case_GETOPT_HELP_CHAR;
case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
@@ -117,6 +126,11 @@ main (int argc, char **argv)
if (ignore_interrupts)
signal (SIGINT, SIG_IGN);
+#ifdef SIGPIPE
+ if (ignore_sigpipe)
+ signal (SIGPIPE, SIG_IGN);
+#endif
+
/* Do *not* warn if tee is given no file arguments.
POSIX requires that it work when given no arguments. */
@@ -192,9 +206,25 @@ tee_files (int nfiles, const char **files)
if (descriptors[i]
&& fwrite (buffer, bytes_read, 1, descriptors[i]) != 1)
{
- error (0, errno, "%s", files[i]);
- descriptors[i] = NULL;
- ok = false;
+#ifdef SIGPIPE
+ if (ignore_sigpipe && errno == EPIPE)
+ {
+ /* Could not write to a pipe with no readers.
+ Close the stream. */
+ fclose (descriptors[i]);
+ /* Close also the underlying file descriptor, to avoid an
+ error message from close_stdout. */
+ if (fileno (descriptors[i]) >= 0)
+ close (fileno (descriptors[i]));
+ descriptors[i] = NULL;
+ }
+ else
+#endif
+ {
+ error (0, errno, "%s", files[i]);
+ descriptors[i] = NULL;
+ ok = false;
+ }
}
}
--
1.5.5.3