]>
Commit | Line | Data |
---|---|---|
9169c9b5 AM |
1 | From 06fe8e801efc0e6a098d93cf104157fb4ef705e8 Mon Sep 17 00:00:00 2001 |
2 | From: "Arnold D. Robbins" <arnold@skeeve.com> | |
3 | Date: Sun, 17 Jun 2018 21:52:28 +0300 | |
4 | Subject: [PATCH] Fix a corner case with EPIPE to stdout/stderr. | |
5 | ||
6 | --- | |
7 | awk.h | 2 +- | |
8 | debug.c | 4 ++-- | |
9 | interpret.h | 6 +++++- | |
10 | io.c | 9 ++++++++- | |
11 | 4 files changed, 16 insertions(+), 5 deletions(-) | |
12 | ||
13 | diff --git a/awk.h b/awk.h | |
14 | index 36e71f2..cdf683d 100644 | |
15 | --- a/awk.h | |
16 | +++ b/awk.h | |
17 | @@ -1581,7 +1581,7 @@ extern struct redirect *redirect_string(const char *redir_exp_str, | |
18 | int *errflg, int extfd, bool failure_fatal); | |
19 | extern NODE *do_close(int nargs); | |
20 | extern int flush_io(void); | |
21 | -extern int close_io(bool *stdio_problem); | |
22 | +extern int close_io(bool *stdio_problem, bool *got_EPIPE); | |
23 | typedef enum { CLOSE_ALL, CLOSE_TO, CLOSE_FROM } two_way_close_type; | |
24 | extern int close_rp(struct redirect *rp, two_way_close_type how); | |
25 | extern int devopen_simple(const char *name, const char *mode, bool try_real_open); | |
26 | diff --git a/debug.c b/debug.c | |
27 | index 3e76ae6..a587d8f 100644 | |
28 | --- a/debug.c | |
29 | +++ b/debug.c | |
30 | @@ -5398,11 +5398,11 @@ save_options(const char *file) | |
31 | static void | |
32 | close_all() | |
33 | { | |
34 | - bool stdio_problem; | |
35 | + bool stdio_problem, got_EPIPE; | |
36 | struct command_source *cs; | |
37 | ||
38 | (void) nextfile(& curfile, true); /* close input data file */ | |
39 | - (void) close_io(& stdio_problem); | |
40 | + (void) close_io(& stdio_problem, & got_EPIPE); | |
41 | if (cur_srcfile->fd != INVALID_HANDLE) { | |
42 | close(cur_srcfile->fd); | |
43 | cur_srcfile->fd = INVALID_HANDLE; | |
44 | diff --git a/interpret.h b/interpret.h | |
45 | index 20fcb7a..8408a53 100644 | |
46 | --- a/interpret.h | |
47 | +++ b/interpret.h | |
48 | @@ -110,6 +110,7 @@ top: | |
49 | case Op_atexit: | |
50 | { | |
51 | bool stdio_problem = false; | |
52 | + bool got_EPIPE = false; | |
53 | ||
54 | /* avoid false source indications */ | |
55 | source = NULL; | |
56 | @@ -125,7 +126,7 @@ top: | |
57 | * and pipes, in that it doesn't affect their exit status. | |
58 | * So we no longer do either. | |
59 | */ | |
60 | - (void) close_io(& stdio_problem); | |
61 | + (void) close_io(& stdio_problem, & got_EPIPE); | |
62 | /* | |
63 | * However, we do want to exit non-zero if there was a problem | |
64 | * with stdout/stderr, so we reinstate a slightly different | |
65 | @@ -135,6 +136,9 @@ top: | |
66 | exit_val = 1; | |
67 | ||
68 | close_extensions(); | |
69 | + | |
70 | + if (got_EPIPE) | |
71 | + die_via_sigpipe(); | |
72 | } | |
73 | break; | |
74 | ||
75 | diff --git a/io.c b/io.c | |
76 | index 1a1d8cc..faccb4b 100644 | |
77 | --- a/io.c | |
78 | +++ b/io.c | |
79 | @@ -1474,12 +1474,13 @@ flush_io() | |
80 | /* close_io --- close all open files, called when exiting */ | |
81 | ||
82 | int | |
83 | -close_io(bool *stdio_problem) | |
84 | +close_io(bool *stdio_problem, bool *got_EPIPE) | |
85 | { | |
86 | struct redirect *rp; | |
87 | struct redirect *next; | |
88 | int status = 0; | |
89 | ||
90 | + *stdio_problem = *got_EPIPE = false; | |
91 | errno = 0; | |
92 | for (rp = red_head; rp != NULL; rp = next) { | |
93 | next = rp->next; | |
94 | @@ -1505,6 +1506,9 @@ close_io(bool *stdio_problem) | |
95 | #endif | |
96 | if (errno != EPIPE) | |
97 | warning(_("error writing standard output (%s)"), strerror(errno)); | |
98 | + else | |
99 | + *got_EPIPE = true; | |
100 | + | |
101 | status++; | |
102 | *stdio_problem = true; | |
103 | } | |
104 | @@ -1515,6 +1519,9 @@ close_io(bool *stdio_problem) | |
105 | #endif | |
106 | if (errno != EPIPE) | |
107 | warning(_("error writing standard error (%s)"), strerror(errno)); | |
108 | + else | |
109 | + *got_EPIPE = true; | |
110 | + | |
111 | status++; | |
112 | *stdio_problem = true; | |
113 | } | |
114 | -- | |
115 | 2.14.4 | |
116 |