summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnold D. Robbins <arnold@skeeve.com>2017-03-27 20:30:14 +0300
committerArnold D. Robbins <arnold@skeeve.com>2017-03-27 20:30:14 +0300
commit5b7042ea0a68d41c4fbd0d6228f77975ebf8c38b (patch)
treeffd5fa8aecdcc0ef3c6c5043c10b0335d4e59435
parent45099c6ece4f4e91f0d525d10a6d4d162d30e6e4 (diff)
downloadgawk-5b7042ea0a68d41c4fbd0d6228f77975ebf8c38b.tar.gz
Die with SIGPIPE when EPIPE happens on stdout.
-rw-r--r--ChangeLog9
-rw-r--r--awk.h2
-rw-r--r--builtin.c4
-rw-r--r--io.c2
-rw-r--r--main.c5
5 files changed, 18 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index d84b38c5..6822c6f4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2017-03-27 Arnold D. Robbins <arnold@skeeve.com>
+
+ Cause EPIPE errors to stdout to generate a real SIGPIPE.
+
+ * awk.h (die_via_sigpipe): New macro.
+ * builtin.c (efwrite): Use it.
+ * io.c (non_fatal_flush_std_file): Ditto.
+ * main.c (usage): Ditto.
+
2017-03-25 Arnold D. Robbins <arnold@skeeve.com>
* io.c (flush_io): Use r_fatal and r_warning for messagefunc
diff --git a/awk.h b/awk.h
index 163ad362..c1e9b4a9 100644
--- a/awk.h
+++ b/awk.h
@@ -1966,7 +1966,9 @@ erealloc_real(void *ptr, size_t count, const char *where, const char *var, const
#ifdef SIGPIPE
#define ignore_sigpipe() signal(SIGPIPE, SIG_IGN)
#define set_sigpipe_to_default() signal(SIGPIPE, SIG_DFL)
+#define die_via_sigpipe() (signal(SIGPIPE, SIG_DFL), kill(getpid(), SIGPIPE))
#else
#define ignore_sigpipe()
#define set_sigpipe_to_default()
+#define die_via_sigpipe() exit(EXIT_FATAL)
#endif
diff --git a/builtin.c b/builtin.c
index 0f2c62f8..e2143b36 100644
--- a/builtin.c
+++ b/builtin.c
@@ -129,9 +129,9 @@ wrerror:
if (errno == 0 || errno == EINVAL)
w32_maybe_set_errno();
#endif
- /* die silently on EPIPE to stdout */
+ /* for stdout, die with a real SIGPIPE, like other awks */
if (fp == stdout && errno == EPIPE)
- gawk_exit(EXIT_SUCCESS); // a la SIGPIPE
+ die_via_sigpipe();
/* otherwise die verbosely */
if ((rp != NULL) ? is_non_fatal_redirect(rp->value, strlen(rp->value)) : is_non_fatal_std(fp))
diff --git a/io.c b/io.c
index fa9225ce..b00f4db4 100644
--- a/io.c
+++ b/io.c
@@ -1400,7 +1400,7 @@ non_fatal_flush_std_file(FILE *fp)
if (is_fatal) {
if (errno == EPIPE)
- exit(EXIT_SUCCESS); // simulate SIGPIPE
+ die_via_sigpipe();
else
fatal(fp == stdout
? _("fflush: cannot flush standard output: %s")
diff --git a/main.c b/main.c
index 4f578d3e..73e63448 100644
--- a/main.c
+++ b/main.c
@@ -633,7 +633,10 @@ By default it reads standard input and writes standard output.\n\n"), fp);
warning(_("error writing standard output (%s)"), strerror(errno));
else if (fp == stderr)
warning(_("error writing standard error (%s)"), strerror(errno));
- }
+ } else if (errno == SIGPIPE)
+ die_via_sigpipe();
+
+ // some other problem than SIGPIPE
exit(EXIT_FAILURE);
}