1 /* Filtering of data through a subprocess.
2 Copyright (C) 2001-2003, 2008-2024 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2009.
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.
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.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>. */
20 #include "pipe-filter.h"
27 #if defined _WIN32 && ! defined __CYGWIN__
29 # include <process.h> /* _beginthreadex, _endthreadex */
30 #elif defined __KLIBC__
34 /* Simple implementation of Win32 APIs */
38 typedef struct _HANDLE
42 unsigned int WINAPI (*start
) (void *);
49 start_wrapper (void *arg
)
51 HANDLE h
= (HANDLE
) arg
;
55 DosPostEventSem (h
->hevDone
);
60 _beginthreadex (void *s
, unsigned n
, unsigned int WINAPI (*start
) (void *),
61 void *arg
, unsigned fl
, unsigned *th
)
65 h
= malloc (sizeof (*h
));
69 if (DosCreateEventSem (NULL
, &h
->hevDone
, 0, FALSE
))
75 h
->tid
= _beginthread (start_wrapper
, NULL
, n
, (void *) h
);
77 goto exit_close_event_sem
;
82 DosCloseEventSem (h
->hevDone
);
91 CloseHandle (HANDLE h
)
93 DosCloseEventSem (h
->hevDone
);
97 # define _endthreadex(x) return (x)
98 # define TerminateThread(h, e) DosKillThread (h->tid)
100 # define GetLastError() (-1)
102 # ifndef ERROR_NO_DATA
103 # define ERROR_NO_DATA 232
106 # define INFINITE SEM_INDEFINITE_WAIT
107 # define WAIT_OBJECT_0 0
110 WaitForSingleObject (HANDLE h
, DWORD ms
)
112 return DosWaitEventSem (h
->hevDone
, ms
) == 0 ? WAIT_OBJECT_0
: (DWORD
) -1;
116 WaitForMultipleObjects (DWORD nCount
, const HANDLE
*pHandles
, BOOL bWaitAll
,
122 ULONG rc
= (ULONG
) -1;
125 psr
= malloc (sizeof (*psr
) * nCount
);
129 for (i
= 0; i
< nCount
; ++i
)
131 psr
[i
].hsemCur
= (HSEM
) pHandles
[i
]->hevDone
;
132 psr
[i
].ulUser
= WAIT_OBJECT_0
+ i
;
135 if (DosCreateMuxWaitSem (NULL
, &hmux
, nCount
, psr
,
136 bWaitAll
? DCMW_WAIT_ALL
: DCMW_WAIT_ANY
))
139 rc
= DosWaitMuxWaitSem (hmux
, ms
, &ulUser
);
140 DosCloseMuxWaitSem (hmux
);
153 # include <sys/select.h>
157 #include "spawn-pipe.h"
158 #include "wait-process.h"
161 #define _(str) gettext (str)
163 #include "pipe-filter-aux.h"
165 #if (defined _WIN32 && ! defined __CYGWIN__) || defined __KLIBC__
169 /* Arguments passed to pipe_filter_ii_execute. */
170 prepare_write_fn prepare_write
;
171 done_write_fn done_write
;
172 prepare_read_fn prepare_read
;
173 done_read_fn done_read
;
175 /* Management of the subprocess. */
179 /* Status of the writer part. */
180 volatile bool writer_terminated
;
181 volatile int writer_errno
;
182 /* Status of the reader part. */
183 volatile bool reader_terminated
;
184 volatile int reader_errno
;
187 static unsigned int WINAPI
188 writer_thread_func (void *thread_arg
)
190 struct locals
*l
= (struct locals
*) thread_arg
;
195 const void *buf
= l
->prepare_write (&bufsize
, l
->private_data
);
199 write (l
->fd
[1], buf
, bufsize
> SSIZE_MAX
? SSIZE_MAX
: bufsize
);
202 /* Don't assume that the gnulib modules 'write' and 'sigpipe' are
204 if (GetLastError () == ERROR_NO_DATA
)
206 l
->writer_errno
= errno
;
209 else if (nwritten
> 0)
210 l
->done_write ((void *) buf
, nwritten
, l
->private_data
);
216 l
->writer_terminated
= true;
217 _endthreadex (0); /* calls ExitThread (0) */
221 static unsigned int WINAPI
222 reader_thread_func (void *thread_arg
)
224 struct locals
*l
= (struct locals
*) thread_arg
;
229 void *buf
= l
->prepare_read (&bufsize
, l
->private_data
);
230 if (!(buf
!= NULL
&& bufsize
> 0))
231 /* prepare_read returned wrong values. */
235 read (l
->fd
[0], buf
, bufsize
> SSIZE_MAX
? SSIZE_MAX
: bufsize
);
238 l
->reader_errno
= errno
;
242 l
->done_read (buf
, nread
, l
->private_data
);
243 else /* nread == 0 */
248 l
->reader_terminated
= true;
249 _endthreadex (0); /* calls ExitThread (0) */
256 pipe_filter_ii_execute (const char *progname
,
257 const char *prog_path
, const char * const *prog_argv
,
258 bool null_stderr
, bool exit_on_error
,
259 prepare_write_fn prepare_write
,
260 done_write_fn done_write
,
261 prepare_read_fn prepare_read
,
262 done_read_fn done_read
,
267 #if !((defined _WIN32 && ! defined __CYGWIN__) || defined __KLIBC__)
268 struct sigaction orig_sigpipe_action
;
271 /* Open a bidirectional pipe to a subprocess. */
272 child
= create_pipe_bidi (progname
, prog_path
, prog_argv
, NULL
,
273 NULL
, null_stderr
, true, exit_on_error
,
278 #if (defined _WIN32 && ! defined __CYGWIN__) || defined __KLIBC__
279 /* Native Windows API. */
280 /* Pipes have a non-blocking mode, see function SetNamedPipeHandleState and
281 the article "Named Pipe Type, Read, and Wait Modes", but Microsoft's
282 documentation discourages its use. So don't use it.
283 Asynchronous I/O is also not suitable because it notifies the caller only
284 about completion of the I/O request, not about intermediate progress.
285 So do the writing and the reading in separate threads. */
289 #define writer_thread_handle handles[0]
290 #define reader_thread_handle handles[1]
291 bool writer_cleaned_up
;
292 bool reader_cleaned_up
;
294 l
.prepare_write
= prepare_write
;
295 l
.done_write
= done_write
;
296 l
.prepare_read
= prepare_read
;
297 l
.done_read
= done_read
;
298 l
.private_data
= private_data
;
301 l
.writer_terminated
= false;
303 l
.reader_terminated
= false;
306 writer_thread_handle
=
307 (HANDLE
) _beginthreadex (NULL
, 100000, writer_thread_func
, &l
, 0, NULL
);
308 reader_thread_handle
=
309 (HANDLE
) _beginthreadex (NULL
, 100000, reader_thread_func
, &l
, 0, NULL
);
310 if (writer_thread_handle
== NULL
|| reader_thread_handle
== NULL
)
313 error (EXIT_FAILURE
, 0, _("creation of threads failed"));
314 if (reader_thread_handle
!= NULL
)
315 CloseHandle (reader_thread_handle
);
316 if (writer_thread_handle
!= NULL
)
317 CloseHandle (writer_thread_handle
);
320 writer_cleaned_up
= false;
321 reader_cleaned_up
= false;
326 /* Here !(writer_cleaned_up && reader_cleaned_up). */
327 if (writer_cleaned_up
)
328 ret
= WaitForSingleObject (reader_thread_handle
, INFINITE
);
329 else if (reader_cleaned_up
)
330 ret
= WaitForSingleObject (writer_thread_handle
, INFINITE
);
332 ret
= WaitForMultipleObjects (2, handles
, FALSE
, INFINITE
);
333 if (!(ret
== WAIT_OBJECT_0
+ 0 || ret
== WAIT_OBJECT_0
+ 1))
336 if (l
.writer_terminated
)
338 /* The writer thread has just terminated. */
339 l
.writer_terminated
= false;
340 CloseHandle (writer_thread_handle
);
344 error (EXIT_FAILURE
, l
.writer_errno
,
345 _("write to %s subprocess failed"), progname
);
346 if (!reader_cleaned_up
)
348 TerminateThread (reader_thread_handle
, 1);
349 CloseHandle (reader_thread_handle
);
353 /* Tell the child there is nothing more the parent will send. */
355 writer_cleaned_up
= true;
357 if (l
.reader_terminated
)
359 /* The reader thread has just terminated. */
360 l
.reader_terminated
= false;
361 CloseHandle (reader_thread_handle
);
365 error (EXIT_FAILURE
, l
.reader_errno
,
366 _("read from %s subprocess failed"), progname
);
367 if (!writer_cleaned_up
)
369 TerminateThread (writer_thread_handle
, 1);
370 CloseHandle (writer_thread_handle
);
374 reader_cleaned_up
= true;
376 if (writer_cleaned_up
&& reader_cleaned_up
)
381 /* When we write to the child process and it has just terminated,
382 we don't want to die from a SIGPIPE signal. So set the SIGPIPE
383 handler to SIG_IGN, and handle EPIPE error codes in write(). */
385 struct sigaction sigpipe_action
;
387 sigpipe_action
.sa_handler
= SIG_IGN
;
388 sigpipe_action
.sa_flags
= 0;
389 sigemptyset (&sigpipe_action
.sa_mask
);
390 if (sigaction (SIGPIPE
, &sigpipe_action
, &orig_sigpipe_action
) < 0)
396 fd_set readfds
; /* All bits except fd[0] are always cleared. */
397 fd_set writefds
; /* All bits except fd[1] are always cleared. */
401 /* Enable non-blocking I/O. This permits the read() and write() calls
402 to return -1/EAGAIN without blocking; this is important for polling
403 if HAVE_SELECT is not defined. It also permits the read() and write()
404 calls to return after partial reads/writes; this is important if
405 HAVE_SELECT is defined, because select() only says that some data
406 can be read or written, not how many. Without non-blocking I/O,
407 Linux 2.2.17 and BSD systems prefer to block instead of returning
408 with partial results. */
412 if ((fcntl_flags
= fcntl (fd
[1], F_GETFL
, 0)) < 0
413 || fcntl (fd
[1], F_SETFL
, fcntl_flags
| O_NONBLOCK
) == -1
414 || (fcntl_flags
= fcntl (fd
[0], F_GETFL
, 0)) < 0
415 || fcntl (fd
[0], F_SETFL
, fcntl_flags
| O_NONBLOCK
) == -1)
418 error (EXIT_FAILURE
, errno
,
419 _("cannot set up nonblocking I/O to %s subprocess"),
429 done_writing
= false;
435 FD_SET (fd
[0], &readfds
);
439 FD_SET (fd
[1], &writefds
);
444 /* Do EINTR handling here instead of in pipe-filter-aux.h,
445 because select() cannot be referred to from an inline
446 function on AIX 7.1. */
448 retval
= select (n
, &readfds
, (!done_writing
? &writefds
: NULL
),
450 while (retval
< 0 && errno
== EINTR
);
456 error (EXIT_FAILURE
, errno
,
457 _("communication with %s subprocess failed"), progname
);
460 if (!done_writing
&& FD_ISSET (fd
[1], &writefds
))
462 if (FD_ISSET (fd
[0], &readfds
))
464 /* How could select() return if none of the two descriptors is ready? */
468 /* Attempt to write. */
475 const void *buf
= prepare_write (&bufsize
, private_data
);
478 /* Writing to a pipe in non-blocking mode is tricky: The
479 write() call may fail with EAGAIN, simply because sufficient
480 space is not available in the pipe. See POSIX:2008
481 <https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html>.
482 This happens actually on AIX and IRIX, when bufsize >= 8192
483 (even though PIPE_BUF and pathconf ("/", _PC_PIPE_BUF) are
485 size_t attempt_to_write
=
486 (bufsize
> SSIZE_MAX
? SSIZE_MAX
: bufsize
);
489 ssize_t nwritten
= write (fd
[1], buf
, attempt_to_write
);
494 attempt_to_write
= attempt_to_write
/ 2;
495 if (attempt_to_write
== 0)
498 else if (!IS_EAGAIN (errno
))
501 error (EXIT_FAILURE
, errno
,
502 _("write to %s subprocess failed"),
510 done_write ((void *) buf
, nwritten
, private_data
);
517 /* Tell the child there is nothing more the parent will send. */
526 /* Attempt to read. */
532 void *buf
= prepare_read (&bufsize
, private_data
);
533 if (!(buf
!= NULL
&& bufsize
> 0))
534 /* prepare_read returned wrong values. */
538 read (fd
[0], buf
, bufsize
> SSIZE_MAX
? SSIZE_MAX
: bufsize
);
541 if (!IS_EAGAIN (errno
))
544 error (EXIT_FAILURE
, errno
,
545 _("read from %s subprocess failed"), progname
);
550 done_read (buf
, nread
, private_data
);
551 else /* nread == 0 */
564 /* Restore SIGPIPE signal handler. */
565 if (sigaction (SIGPIPE
, &orig_sigpipe_action
, NULL
) < 0)
571 /* Remove zombie process from process list. */
574 wait_subprocess (child
, progname
, false, null_stderr
,
575 true, exit_on_error
, NULL
);
576 if (exitstatus
!= 0 && exit_on_error
)
577 error (EXIT_FAILURE
, 0, _("%s subprocess terminated with exit code %d"),
578 progname
, exitstatus
);
584 int saved_errno
= errno
;
586 #if !((defined _WIN32 && ! defined __CYGWIN__) || defined __KLIBC__)
587 if (sigaction (SIGPIPE
, &orig_sigpipe_action
, NULL
) < 0)
591 wait_subprocess (child
, progname
, true, true, true, false, NULL
);