Mercurial > hg > octave-kai > gnulib-hg
annotate lib/pipe-filter-ii.c @ 17160:72f4bab621be
fts: introduce FTS_VERBATIM
This gives clients the option to disable stripping of trailing slashes
from input path names during fts_open initialization.
The recent change v0.0-7611-g3a9002d that made fts_open strip trailing
slashes from input path names had a negative impact on findutils that
relies on the old fts_open behavior to implement POSIX requirement that
each path operand of the find utility shall be evaluated unaltered as it
was provided, including all trailing slash characters.
* lib/fts_.h (FTS_VERBATIM): New bit flag.
(FTS_OPTIONMASK, FTS_NAMEONLY, FTS_STOP): Adjust.
* lib/fts.c (fts_open): Honor it.
author | Dmitry V. Levin <ldv@altlinux.org> |
---|---|
date | Sun, 18 Nov 2012 04:40:18 +0400 |
parents | a712776b11ce |
children | e542fd46ad6f |
rev | line source |
---|---|
11758 | 1 /* Filtering of data through a subprocess. |
16201
8250f2777afc
maint: update all copyright year number ranges
Jim Meyering <meyering@redhat.com>
parents:
14870
diff
changeset
|
2 Copyright (C) 2001-2003, 2008-2012 Free Software Foundation, Inc. |
11758 | 3 Written by Bruno Haible <bruno@clisp.org>, 2009. |
4 | |
5 This program is free software: you can redistribute it and/or modify | |
6 it under the terms of the GNU General Public License as published by | |
7 the Free Software Foundation; either version 3 of the License, or | |
8 (at your option) any later version. | |
9 | |
10 This program is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 GNU General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU General Public License | |
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
17 | |
18 #include <config.h> | |
19 | |
20 #include "pipe-filter.h" | |
21 | |
22 #include <errno.h> | |
23 #include <fcntl.h> | |
24 #include <stdbool.h> | |
25 #include <stdint.h> | |
26 #include <stdlib.h> | |
27 #include <unistd.h> | |
28 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ | |
29 # include <windows.h> | |
30 #else | |
31 # include <signal.h> | |
32 # include <sys/select.h> | |
33 #endif | |
34 | |
35 #include "error.h" | |
13924
5be0c314f2f8
Rename module 'pipe' to 'spawn-pipe'.
Bruno Haible <bruno@clisp.org>
parents:
12559
diff
changeset
|
36 #include "spawn-pipe.h" |
11758 | 37 #include "wait-process.h" |
38 #include "gettext.h" | |
39 | |
40 #define _(str) gettext (str) | |
41 | |
42 #include "pipe-filter-aux.h" | |
43 | |
44 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ | |
45 | |
46 struct locals | |
47 { | |
48 /* Arguments passed to pipe_filter_ii_execute. */ | |
49 prepare_write_fn prepare_write; | |
50 done_write_fn done_write; | |
51 prepare_read_fn prepare_read; | |
52 done_read_fn done_read; | |
53 | |
54 /* Management of the subprocess. */ | |
55 void *private_data; | |
56 int fd[2]; | |
57 | |
58 /* Status of the writer part. */ | |
59 volatile bool writer_terminated; | |
60 volatile int writer_errno; | |
61 /* Status of the reader part. */ | |
62 volatile bool reader_terminated; | |
63 volatile int reader_errno; | |
64 }; | |
65 | |
66 static unsigned int WINAPI | |
67 writer_thread_func (void *thread_arg) | |
68 { | |
69 struct locals *l = (struct locals *) thread_arg; | |
70 | |
71 for (;;) | |
72 { | |
73 size_t bufsize; | |
74 const void *buf = l->prepare_write (&bufsize, l->private_data); | |
75 if (buf != NULL) | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
76 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
77 ssize_t nwritten = |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
78 write (l->fd[1], buf, bufsize > SSIZE_MAX ? SSIZE_MAX : bufsize); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
79 if (nwritten < 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
80 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
81 /* Don't assume that the gnulib modules 'write' and 'sigpipe' are |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
82 used. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
83 if (GetLastError () == ERROR_NO_DATA) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
84 errno = EPIPE; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
85 l->writer_errno = errno; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
86 break; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
87 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
88 else if (nwritten > 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
89 l->done_write ((void *) buf, nwritten, l->private_data); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
90 } |
11758 | 91 else |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
92 break; |
11758 | 93 } |
94 | |
95 l->writer_terminated = true; | |
96 _endthreadex (0); /* calls ExitThread (0) */ | |
97 abort (); | |
98 } | |
99 | |
100 static unsigned int WINAPI | |
101 reader_thread_func (void *thread_arg) | |
102 { | |
103 struct locals *l = (struct locals *) thread_arg; | |
104 | |
105 for (;;) | |
106 { | |
107 size_t bufsize; | |
108 void *buf = l->prepare_read (&bufsize, l->private_data); | |
109 if (!(buf != NULL && bufsize > 0)) | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
110 /* prepare_read returned wrong values. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
111 abort (); |
11758 | 112 { |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
113 ssize_t nread = |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
114 read (l->fd[0], buf, bufsize > SSIZE_MAX ? SSIZE_MAX : bufsize); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
115 if (nread < 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
116 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
117 l->reader_errno = errno; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
118 break; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
119 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
120 else if (nread > 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
121 l->done_read (buf, nread, l->private_data); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
122 else /* nread == 0 */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
123 break; |
11758 | 124 } |
125 } | |
126 | |
127 l->reader_terminated = true; | |
128 _endthreadex (0); /* calls ExitThread (0) */ | |
129 abort (); | |
130 } | |
131 | |
132 #endif | |
133 | |
134 int | |
135 pipe_filter_ii_execute (const char *progname, | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
136 const char *prog_path, const char **prog_argv, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
137 bool null_stderr, bool exit_on_error, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
138 prepare_write_fn prepare_write, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
139 done_write_fn done_write, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
140 prepare_read_fn prepare_read, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
141 done_read_fn done_read, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
142 void *private_data) |
11758 | 143 { |
144 pid_t child; | |
145 int fd[2]; | |
146 #if !((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) | |
147 struct sigaction orig_sigpipe_action; | |
148 #endif | |
149 | |
150 /* Open a bidirectional pipe to a subprocess. */ | |
151 child = create_pipe_bidi (progname, prog_path, (char **) prog_argv, | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
152 null_stderr, true, exit_on_error, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
153 fd); |
11758 | 154 if (child == -1) |
155 return -1; | |
156 | |
157 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ | |
16242
59c686e5b2df
Talk about "native Windows API", not "Woe32".
Bruno Haible <bruno@clisp.org>
parents:
16201
diff
changeset
|
158 /* Native Windows API. */ |
11758 | 159 /* Pipes have a non-blocking mode, see function SetNamedPipeHandleState and |
160 the article "Named Pipe Type, Read, and Wait Modes", but Microsoft's | |
161 documentation discourages its use. So don't use it. | |
162 Asynchronous I/O is also not suitable because it notifies the caller only | |
163 about completion of the I/O request, not about intermediate progress. | |
164 So do the writing and the reading in separate threads. */ | |
165 { | |
166 struct locals l; | |
167 HANDLE handles[2]; | |
168 #define writer_thread_handle handles[0] | |
169 #define reader_thread_handle handles[1] | |
170 bool writer_cleaned_up; | |
171 bool reader_cleaned_up; | |
172 | |
173 l.prepare_write = prepare_write; | |
174 l.done_write = done_write; | |
175 l.prepare_read = prepare_read; | |
176 l.done_read = done_read; | |
177 l.private_data = private_data; | |
178 l.fd[0] = fd[0]; | |
179 l.fd[1] = fd[1]; | |
180 l.writer_terminated = false; | |
181 l.writer_errno = 0; | |
182 l.reader_terminated = false; | |
183 l.reader_errno = 0; | |
184 | |
185 writer_thread_handle = | |
186 (HANDLE) _beginthreadex (NULL, 100000, writer_thread_func, &l, 0, NULL); | |
187 reader_thread_handle = | |
188 (HANDLE) _beginthreadex (NULL, 100000, reader_thread_func, &l, 0, NULL); | |
189 if (writer_thread_handle == NULL || reader_thread_handle == NULL) | |
190 { | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
191 if (exit_on_error) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
192 error (EXIT_FAILURE, 0, _("creation of threads failed")); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
193 if (reader_thread_handle != NULL) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
194 CloseHandle (reader_thread_handle); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
195 if (writer_thread_handle != NULL) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
196 CloseHandle (writer_thread_handle); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
197 goto fail; |
11758 | 198 } |
199 writer_cleaned_up = false; | |
200 reader_cleaned_up = false; | |
201 for (;;) | |
202 { | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
203 DWORD ret; |
11758 | 204 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
205 /* Here !(writer_cleaned_up && reader_cleaned_up). */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
206 if (writer_cleaned_up) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
207 ret = WaitForSingleObject (reader_thread_handle, INFINITE); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
208 else if (reader_cleaned_up) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
209 ret = WaitForSingleObject (writer_thread_handle, INFINITE); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
210 else |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
211 ret = WaitForMultipleObjects (2, handles, FALSE, INFINITE); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
212 if (!(ret == WAIT_OBJECT_0 + 0 || ret == WAIT_OBJECT_0 + 1)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
213 abort (); |
11758 | 214 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
215 if (l.writer_terminated) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
216 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
217 /* The writer thread has just terminated. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
218 l.writer_terminated = false; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
219 CloseHandle (writer_thread_handle); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
220 if (l.writer_errno) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
221 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
222 if (exit_on_error) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
223 error (EXIT_FAILURE, l.writer_errno, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
224 _("write to %s subprocess failed"), progname); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
225 if (!reader_cleaned_up) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
226 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
227 TerminateThread (reader_thread_handle, 1); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
228 CloseHandle (reader_thread_handle); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
229 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
230 goto fail; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
231 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
232 /* Tell the child there is nothing more the parent will send. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
233 close (fd[1]); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
234 writer_cleaned_up = true; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
235 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
236 if (l.reader_terminated) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
237 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
238 /* The reader thread has just terminated. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
239 l.reader_terminated = false; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
240 CloseHandle (reader_thread_handle); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
241 if (l.reader_errno) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
242 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
243 if (exit_on_error) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
244 error (EXIT_FAILURE, l.reader_errno, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
245 _("read from %s subprocess failed"), progname); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
246 if (!writer_cleaned_up) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
247 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
248 TerminateThread (writer_thread_handle, 1); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
249 CloseHandle (writer_thread_handle); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
250 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
251 goto fail; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
252 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
253 reader_cleaned_up = true; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
254 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
255 if (writer_cleaned_up && reader_cleaned_up) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
256 break; |
11758 | 257 } |
258 } | |
259 #else | |
260 /* When we write to the child process and it has just terminated, | |
261 we don't want to die from a SIGPIPE signal. So set the SIGPIPE | |
262 handler to SIG_IGN, and handle EPIPE error codes in write(). */ | |
263 { | |
264 struct sigaction sigpipe_action; | |
265 | |
266 sigpipe_action.sa_handler = SIG_IGN; | |
267 sigpipe_action.sa_flags = 0; | |
268 sigemptyset (&sigpipe_action.sa_mask); | |
269 if (sigaction (SIGPIPE, &sigpipe_action, &orig_sigpipe_action) < 0) | |
270 abort (); | |
271 } | |
272 | |
273 { | |
274 # if HAVE_SELECT | |
275 fd_set readfds; /* All bits except fd[0] are always cleared. */ | |
276 fd_set writefds; /* All bits except fd[1] are always cleared. */ | |
277 # endif | |
278 bool done_writing; | |
279 | |
280 /* Enable non-blocking I/O. This permits the read() and write() calls | |
281 to return -1/EAGAIN without blocking; this is important for polling | |
282 if HAVE_SELECT is not defined. It also permits the read() and write() | |
283 calls to return after partial reads/writes; this is important if | |
284 HAVE_SELECT is defined, because select() only says that some data | |
285 can be read or written, not how many. Without non-blocking I/O, | |
286 Linux 2.2.17 and BSD systems prefer to block instead of returning | |
287 with partial results. */ | |
288 { | |
289 int fcntl_flags; | |
290 | |
291 if ((fcntl_flags = fcntl (fd[1], F_GETFL, 0)) < 0 | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
292 || fcntl (fd[1], F_SETFL, fcntl_flags | O_NONBLOCK) == -1 |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
293 || (fcntl_flags = fcntl (fd[0], F_GETFL, 0)) < 0 |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
294 || fcntl (fd[0], F_SETFL, fcntl_flags | O_NONBLOCK) == -1) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
295 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
296 if (exit_on_error) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
297 error (EXIT_FAILURE, errno, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
298 _("cannot set up nonblocking I/O to %s subprocess"), |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
299 progname); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
300 goto fail; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
301 } |
11758 | 302 } |
303 | |
304 # if HAVE_SELECT | |
305 FD_ZERO (&readfds); | |
306 FD_ZERO (&writefds); | |
307 # endif | |
308 done_writing = false; | |
309 for (;;) | |
310 { | |
311 # if HAVE_SELECT | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
312 int n; |
11758 | 313 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
314 FD_SET (fd[0], &readfds); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
315 n = fd[0] + 1; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
316 if (!done_writing) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
317 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
318 FD_SET (fd[1], &writefds); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
319 if (n <= fd[1]) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
320 n = fd[1] + 1; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
321 } |
11758 | 322 |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
323 n = select (n, &readfds, (!done_writing ? &writefds : NULL), NULL, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
324 NULL); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
325 if (n < 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
326 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
327 if (exit_on_error) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
328 error (EXIT_FAILURE, errno, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
329 _("communication with %s subprocess failed"), progname); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
330 goto fail; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
331 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
332 if (!done_writing && FD_ISSET (fd[1], &writefds)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
333 goto try_write; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
334 if (FD_ISSET (fd[0], &readfds)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
335 goto try_read; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
336 /* How could select() return if none of the two descriptors is ready? */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
337 abort (); |
11758 | 338 # endif |
339 | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
340 /* Attempt to write. */ |
11758 | 341 # if HAVE_SELECT |
342 try_write: | |
343 # endif | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
344 if (!done_writing) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
345 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
346 size_t bufsize; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
347 const void *buf = prepare_write (&bufsize, private_data); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
348 if (buf != NULL) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
349 { |
14870
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
350 /* Writing to a pipe in non-blocking mode is tricky: The |
16358 | 351 write() call may fail with EAGAIN, simply because sufficient |
14870
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
352 space is not available in the pipe. See POSIX:2008 |
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
353 <http://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html>. |
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
354 This happens actually on AIX and IRIX, when bufsize >= 8192 |
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
355 (even though PIPE_BUF and pathconf ("/", _PC_PIPE_BUF) are |
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
356 both 32768). */ |
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
357 size_t attempt_to_write = |
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
358 (bufsize > SSIZE_MAX ? SSIZE_MAX : bufsize); |
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
359 for (;;) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
360 { |
14870
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
361 ssize_t nwritten = write (fd[1], buf, attempt_to_write); |
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
362 if (nwritten < 0) |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
363 { |
14870
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
364 if (errno == EAGAIN) |
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
365 { |
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
366 attempt_to_write = attempt_to_write / 2; |
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
367 if (attempt_to_write == 0) |
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
368 break; |
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
369 } |
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
370 else if (!IS_EAGAIN (errno)) |
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
371 { |
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
372 if (exit_on_error) |
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
373 error (EXIT_FAILURE, errno, |
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
374 _("write to %s subprocess failed"), |
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
375 progname); |
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
376 goto fail; |
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
377 } |
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
378 } |
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
379 else |
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
380 { |
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
381 if (nwritten > 0) |
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
382 done_write ((void *) buf, nwritten, private_data); |
d52404af0321
pipe-filter-ii: Fix test failure on AIX and IRIX.
Bruno Haible <bruno@clisp.org>
parents:
14079
diff
changeset
|
383 break; |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
384 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
385 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
386 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
387 else |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
388 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
389 /* Tell the child there is nothing more the parent will send. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
390 close (fd[1]); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
391 done_writing = true; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
392 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
393 } |
11758 | 394 # if HAVE_SELECT |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
395 continue; |
11758 | 396 # endif |
397 | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
398 /* Attempt to read. */ |
11758 | 399 # if HAVE_SELECT |
400 try_read: | |
401 # endif | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
402 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
403 size_t bufsize; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
404 void *buf = prepare_read (&bufsize, private_data); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
405 if (!(buf != NULL && bufsize > 0)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
406 /* prepare_read returned wrong values. */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
407 abort (); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
408 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
409 ssize_t nread = |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
410 read (fd[0], buf, bufsize > SSIZE_MAX ? SSIZE_MAX : bufsize); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
411 if (nread < 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
412 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
413 if (!IS_EAGAIN (errno)) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
414 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
415 if (exit_on_error) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
416 error (EXIT_FAILURE, errno, |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
417 _("read from %s subprocess failed"), progname); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
418 goto fail; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
419 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
420 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
421 else if (nread > 0) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
422 done_read (buf, nread, private_data); |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
423 else /* nread == 0 */ |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
424 { |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
425 if (done_writing) |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
426 break; |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
427 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
428 } |
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
429 } |
11758 | 430 # if HAVE_SELECT |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
431 continue; |
11758 | 432 # endif |
433 } | |
434 } | |
435 | |
436 /* Restore SIGPIPE signal handler. */ | |
437 if (sigaction (SIGPIPE, &orig_sigpipe_action, NULL) < 0) | |
438 abort (); | |
439 #endif | |
440 | |
441 close (fd[0]); | |
442 | |
443 /* Remove zombie process from process list. */ | |
444 { | |
445 int exitstatus = | |
446 wait_subprocess (child, progname, false, null_stderr, | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
447 true, exit_on_error, NULL); |
11758 | 448 if (exitstatus != 0 && exit_on_error) |
449 error (EXIT_FAILURE, 0, _("%s subprocess terminated with exit code %d"), | |
12421
e8d2c6fc33ad
Use spaces for indentation, not tabs.
Bruno Haible <bruno@clisp.org>
parents:
11873
diff
changeset
|
450 progname, exitstatus); |
11758 | 451 return exitstatus; |
452 } | |
453 | |
454 fail: | |
455 { | |
456 int saved_errno = errno; | |
457 close (fd[1]); | |
458 #if !((defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__) | |
459 if (sigaction (SIGPIPE, &orig_sigpipe_action, NULL) < 0) | |
460 abort (); | |
461 #endif | |
462 close (fd[0]); | |
463 wait_subprocess (child, progname, true, true, true, false, NULL); | |
464 errno = saved_errno; | |
465 return -1; | |
466 } | |
467 } |