From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from fennec.apple.relay.mailchannels.net (fennec.apple.relay.mailchannels.net [23.83.208.58]) by sourceware.org (Postfix) with ESMTPS id 88A0D395543F for ; Wed, 14 Apr 2021 06:21:32 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 88A0D395543F X-Sender-Id: dreamhost|x-authsender|siddhesh@gotplt.org Received: from relay.mailchannels.net (localhost [127.0.0.1]) by relay.mailchannels.net (Postfix) with ESMTP id 7A3F9401CAA; Wed, 14 Apr 2021 06:21:31 +0000 (UTC) Received: from pdx1-sub0-mail-a20.g.dreamhost.com (100-98-55-74.trex.outbound.svc.cluster.local [100.98.55.74]) (Authenticated sender: dreamhost) by relay.mailchannels.net (Postfix) with ESMTPA id 0B404401C6E; Wed, 14 Apr 2021 06:21:31 +0000 (UTC) X-Sender-Id: dreamhost|x-authsender|siddhesh@gotplt.org Received: from pdx1-sub0-mail-a20.g.dreamhost.com (pop.dreamhost.com [64.90.62.162]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384) by 100.98.55.74 (trex/6.1.1); Wed, 14 Apr 2021 06:21:31 +0000 X-MC-Relay: Good X-MailChannels-SenderId: dreamhost|x-authsender|siddhesh@gotplt.org X-MailChannels-Auth-Id: dreamhost X-Exultant-Arch: 215b7d141260747a_1618381291352_1114635692 X-MC-Loop-Signature: 1618381291352:3760983954 X-MC-Ingress-Time: 1618381291351 Received: from pdx1-sub0-mail-a20.g.dreamhost.com (localhost [127.0.0.1]) by pdx1-sub0-mail-a20.g.dreamhost.com (Postfix) with ESMTP id B85457EFBB; Tue, 13 Apr 2021 23:21:30 -0700 (PDT) Received: from rhbox.intra.reserved-bit.com (unknown [1.186.101.110]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) (Authenticated sender: siddhesh@gotplt.org) by pdx1-sub0-mail-a20.g.dreamhost.com (Postfix) with ESMTPSA id C2AC27EFB7; Tue, 13 Apr 2021 23:21:27 -0700 (PDT) X-DH-BACKEND: pdx1-sub0-mail-a20 From: Siddhesh Poyarekar To: libc-stable@sourceware.org Cc: Adhemerval Zanella , Carlos O'Donell Subject: [COMMITTED 2.28 1/7] support: Add support_capture_subprogram Date: Wed, 14 Apr 2021 11:51:12 +0530 Message-Id: <20210414062118.1411358-1-siddhesh@sourceware.org> X-Mailer: git-send-email 2.29.2 MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Spam-Status: No, score=-3494.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, JMQ_SPF_NEUTRAL, KAM_DMARC_NONE, KAM_DMARC_STATUS, KAM_SHORT, RCVD_IN_BARRACUDACENTRAL, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NEUTRAL, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: libc-stable@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-stable mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 14 Apr 2021 06:21:36 -0000 From: Adhemerval Zanella Its API is similar to support_capture_subprocess, but rather creates a new process based on the input path and arguments. Under the hoods it uses posix_spawn to create the new process. It also allows the use of other support_capture_* functions to check for expected results and free the resources. Checked on x86_64-linux-gnu. * support/Makefile (libsupport-routines): Add support_subprocess, xposix_spawn, xposix_spawn_file_actions_addclose, and xposix_spawn_file_actions_adddup2. (tst-support_capture_subprocess-ARGS): New rule. * support/capture_subprocess.h (support_capture_subprogram): New prototype. * support/support_capture_subprocess.c (support_capture_subprocess): Refactor to use support_subprocess and support_capture_poll. (support_capture_subprogram): New function. * support/tst-support_capture_subprocess.c (write_mode_to_str, str_to_write_mode, test_common, parse_int, handle_restart, do_subprocess, do_subprogram, do_multiple_tests): New functions. (do_test): Add support_capture_subprogram tests. * support/subprocess.h: New file. * support/support_subprocess.c: Likewise. * support/xposix_spawn.c: Likewise. * support/xposix_spawn_file_actions_addclose.c: Likewise. * support/xposix_spawn_file_actions_adddup2.c: Likewise. * support/xspawn.h: Likewise. Reviewed-by: Carlos O'Donell (cherry picked from commit 0e169691290a6d2187a4ff41495fc5678cbfdcdc) --- support/Makefile | 6 + support/capture_subprocess.h | 6 + support/subprocess.h | 49 +++++ support/support_capture_subprocess.c | 80 ++++---- support/support_subprocess.c | 152 +++++++++++++++ support/tst-support_capture_subprocess.c | 183 ++++++++++++++++++- support/xposix_spawn.c | 32 ++++ support/xposix_spawn_file_actions_addclose.c | 29 +++ support/xposix_spawn_file_actions_adddup2.c | 30 +++ support/xspawn.h | 34 ++++ 10 files changed, 551 insertions(+), 50 deletions(-) create mode 100644 support/subprocess.h create mode 100644 support/support_subprocess.c create mode 100644 support/xposix_spawn.c create mode 100644 support/xposix_spawn_file_actions_addclose.c create mode 100644 support/xposix_spawn_file_actions_adddup2.c create mode 100644 support/xspawn.h diff --git a/support/Makefile b/support/Makefile index 3c0d870c96..ac204f59fa 100644 --- a/support/Makefile +++ b/support/Makefile @@ -60,6 +60,7 @@ libsupport-routines =3D \ support_record_failure \ support_run_diff \ support_shared_allocate \ + support_subprocess \ support_test_compare_blob \ support_test_compare_failure \ support_write_file_string \ @@ -143,6 +144,9 @@ libsupport-routines =3D \ xsigaction \ xsignal \ xsocket \ + xposix_spawn \ + xposix_spawn_file_actions_addclose \ + xposix_spawn_file_actions_adddup2 \ xstrdup \ xstrndup \ xsysconf \ @@ -185,4 +189,6 @@ endif =20 $(objpfx)tst-support_format_dns_packet: $(common-objpfx)resolv/libresolv= .so =20 +tst-support_capture_subprocess-ARGS =3D -- $(host-test-program-cmd) + include ../Rules diff --git a/support/capture_subprocess.h b/support/capture_subprocess.h index b0886ba1d1..d5eac84d09 100644 --- a/support/capture_subprocess.h +++ b/support/capture_subprocess.h @@ -35,6 +35,12 @@ struct support_capture_subprocess struct support_capture_subprocess support_capture_subprocess (void (*callback) (void *), void *closure); =20 +/* Issue FILE with ARGV arguments by using posix_spawn and capture stand= ard + output, standard error, and the exit status. The out.buffer and err.= buffer + are handle as support_capture_subprocess. */ +struct support_capture_subprocess support_capture_subprogram + (const char *file, char *const argv[]); + /* Deallocate the subprocess data captured by support_capture_subprocess. */ void support_capture_subprocess_free (struct support_capture_subprocess = *); diff --git a/support/subprocess.h b/support/subprocess.h new file mode 100644 index 0000000000..c031878d94 --- /dev/null +++ b/support/subprocess.h @@ -0,0 +1,49 @@ +/* Create a subprocess. + Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef SUPPORT_SUBPROCESS_H +#define SUPPORT_SUBPROCESS_H + +#include + +struct support_subprocess +{ + int stdout_pipe[2]; + int stderr_pipe[2]; + pid_t pid; +}; + +/* Invoke CALLBACK (CLOSURE) in a subprocess created with fork and retur= n + its PID, a pipe redirected to STDOUT, and a pipe redirected to STDERR= . */ +struct support_subprocess support_subprocess + (void (*callback) (void *), void *closure); + +/* Issue FILE with ARGV arguments by using posix_spawn and return is PID= , a + pipe redirected to STDOUT, and a pipe redirected to STDERR. */ +struct support_subprocess support_subprogram + (const char *file, char *const argv[]); + +/* Wait for the subprocess indicated by PROC::PID. Return the status + indicate by waitpid call. */ +int support_process_wait (struct support_subprocess *proc); + +/* Terminate the subprocess indicated by PROC::PID, first with a SIGTERM= and + then with a SIGKILL. Return the status as for waitpid call. */ +int support_process_terminate (struct support_subprocess *proc); + +#endif diff --git a/support/support_capture_subprocess.c b/support/support_captu= re_subprocess.c index 93f6ea3102..8a18e586cc 100644 --- a/support/support_capture_subprocess.c +++ b/support/support_capture_subprocess.c @@ -16,6 +16,7 @@ License along with the GNU C Library; if not, see . */ =20 +#include #include =20 #include @@ -23,6 +24,7 @@ #include #include #include +#include =20 static void transfer (const char *what, struct pollfd *pfd, struct xmemstream *strea= m) @@ -50,59 +52,53 @@ transfer (const char *what, struct pollfd *pfd, struc= t xmemstream *stream) } } =20 -struct support_capture_subprocess -support_capture_subprocess (void (*callback) (void *), void *closure) +static void +support_capture_poll (struct support_capture_subprocess *result, + struct support_subprocess *proc) { - struct support_capture_subprocess result; - xopen_memstream (&result.out); - xopen_memstream (&result.err); - - int stdout_pipe[2]; - xpipe (stdout_pipe); - TEST_VERIFY (stdout_pipe[0] > STDERR_FILENO); - TEST_VERIFY (stdout_pipe[1] > STDERR_FILENO); - int stderr_pipe[2]; - xpipe (stderr_pipe); - TEST_VERIFY (stderr_pipe[0] > STDERR_FILENO); - TEST_VERIFY (stderr_pipe[1] > STDERR_FILENO); - - TEST_VERIFY (fflush (stdout) =3D=3D 0); - TEST_VERIFY (fflush (stderr) =3D=3D 0); - - pid_t pid =3D xfork (); - if (pid =3D=3D 0) - { - xclose (stdout_pipe[0]); - xclose (stderr_pipe[0]); - xdup2 (stdout_pipe[1], STDOUT_FILENO); - xdup2 (stderr_pipe[1], STDERR_FILENO); - xclose (stdout_pipe[1]); - xclose (stderr_pipe[1]); - callback (closure); - _exit (0); - } - xclose (stdout_pipe[1]); - xclose (stderr_pipe[1]); - struct pollfd fds[2] =3D { - { .fd =3D stdout_pipe[0], .events =3D POLLIN }, - { .fd =3D stderr_pipe[0], .events =3D POLLIN }, + { .fd =3D proc->stdout_pipe[0], .events =3D POLLIN }, + { .fd =3D proc->stderr_pipe[0], .events =3D POLLIN }, }; =20 do { xpoll (fds, 2, -1); - transfer ("stdout", &fds[0], &result.out); - transfer ("stderr", &fds[1], &result.err); + transfer ("stdout", &fds[0], &result->out); + transfer ("stderr", &fds[1], &result->err); } while (fds[0].events !=3D 0 || fds[1].events !=3D 0); - xclose (stdout_pipe[0]); - xclose (stderr_pipe[0]); =20 - xfclose_memstream (&result.out); - xfclose_memstream (&result.err); - xwaitpid (pid, &result.status, 0); + xfclose_memstream (&result->out); + xfclose_memstream (&result->err); + + result->status =3D support_process_wait (proc); +} + +struct support_capture_subprocess +support_capture_subprocess (void (*callback) (void *), void *closure) +{ + struct support_capture_subprocess result; + xopen_memstream (&result.out); + xopen_memstream (&result.err); + + struct support_subprocess proc =3D support_subprocess (callback, closu= re); + + support_capture_poll (&result, &proc); + return result; +} + +struct support_capture_subprocess +support_capture_subprogram (const char *file, char *const argv[]) +{ + struct support_capture_subprocess result; + xopen_memstream (&result.out); + xopen_memstream (&result.err); + + struct support_subprocess proc =3D support_subprogram (file, argv); + + support_capture_poll (&result, &proc); return result; } =20 diff --git a/support/support_subprocess.c b/support/support_subprocess.c new file mode 100644 index 0000000000..0c8cc6af30 --- /dev/null +++ b/support/support_subprocess.c @@ -0,0 +1,152 @@ +/* Create subprocess. + Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct support_subprocess +support_suprocess_init (void) +{ + struct support_subprocess result; + + xpipe (result.stdout_pipe); + TEST_VERIFY (result.stdout_pipe[0] > STDERR_FILENO); + TEST_VERIFY (result.stdout_pipe[1] > STDERR_FILENO); + + xpipe (result.stderr_pipe); + TEST_VERIFY (result.stderr_pipe[0] > STDERR_FILENO); + TEST_VERIFY (result.stderr_pipe[1] > STDERR_FILENO); + + TEST_VERIFY (fflush (stdout) =3D=3D 0); + TEST_VERIFY (fflush (stderr) =3D=3D 0); + + return result; +} + +struct support_subprocess +support_subprocess (void (*callback) (void *), void *closure) +{ + struct support_subprocess result =3D support_suprocess_init (); + + result.pid =3D xfork (); + if (result.pid =3D=3D 0) + { + xclose (result.stdout_pipe[0]); + xclose (result.stderr_pipe[0]); + xdup2 (result.stdout_pipe[1], STDOUT_FILENO); + xdup2 (result.stderr_pipe[1], STDERR_FILENO); + xclose (result.stdout_pipe[1]); + xclose (result.stderr_pipe[1]); + callback (closure); + _exit (0); + } + xclose (result.stdout_pipe[1]); + xclose (result.stderr_pipe[1]); + + return result; +} + +struct support_subprocess +support_subprogram (const char *file, char *const argv[]) +{ + struct support_subprocess result =3D support_suprocess_init (); + + posix_spawn_file_actions_t fa; + /* posix_spawn_file_actions_init does not fail. */ + posix_spawn_file_actions_init (&fa); + + xposix_spawn_file_actions_addclose (&fa, result.stdout_pipe[0]); + xposix_spawn_file_actions_addclose (&fa, result.stderr_pipe[0]); + xposix_spawn_file_actions_adddup2 (&fa, result.stdout_pipe[1], STDOUT_= FILENO); + xposix_spawn_file_actions_adddup2 (&fa, result.stderr_pipe[1], STDERR_= FILENO); + xposix_spawn_file_actions_addclose (&fa, result.stdout_pipe[1]); + xposix_spawn_file_actions_addclose (&fa, result.stderr_pipe[1]); + + result.pid =3D xposix_spawn (file, &fa, NULL, argv, NULL); + + xclose (result.stdout_pipe[1]); + xclose (result.stderr_pipe[1]); + + return result; +} + +int +support_process_wait (struct support_subprocess *proc) +{ + xclose (proc->stdout_pipe[0]); + xclose (proc->stderr_pipe[0]); + + int status; + xwaitpid (proc->pid, &status, 0); + return status; +} + + +static bool +support_process_kill (int pid, int signo, int *status) +{ + /* Kill the whole process group. */ + kill (-pid, signo); + /* In case setpgid failed in the child, kill it individually too. */ + kill (pid, signo); + + /* Wait for it to terminate. */ + pid_t killed; + for (int i =3D 0; i < 5; ++i) + { + int status; + killed =3D xwaitpid (pid, &status, WNOHANG|WUNTRACED); + if (killed !=3D 0) + break; + + /* Delay, give the system time to process the kill. If the + nanosleep() call return prematurely, all the better. We + won't restart it since this probably means the child process + finally died. */ + nanosleep (&((struct timespec) { 0, 100000000 }), NULL); + } + if (killed !=3D 0 && killed !=3D pid) + return false; + + return true; +} + +int +support_process_terminate (struct support_subprocess *proc) +{ + xclose (proc->stdout_pipe[0]); + xclose (proc->stderr_pipe[0]); + + int status; + pid_t killed =3D xwaitpid (proc->pid, &status, WNOHANG|WUNTRACED); + if (killed !=3D 0 && killed =3D=3D proc->pid) + return status; + + /* Subprocess is still running, terminate it. */ + if (!support_process_kill (proc->pid, SIGTERM, &status) ) + support_process_kill (proc->pid, SIGKILL, &status); + + return status; +} diff --git a/support/tst-support_capture_subprocess.c b/support/tst-suppo= rt_capture_subprocess.c index a685256091..bfa1c181c5 100644 --- a/support/tst-support_capture_subprocess.c +++ b/support/tst-support_capture_subprocess.c @@ -23,8 +23,20 @@ #include #include #include +#include #include #include +#include +#include +#include +#include +#include + +/* Nonzero if the program gets called via 'exec'. */ +static int restart; + +/* Hold the four initial argument used to respawn the process. */ +static char *initial_argv[5]; =20 /* Write one byte at *P to FD and advance *P. Do nothing if *P is '\0'. */ @@ -42,6 +54,30 @@ transfer (const unsigned char **p, int fd) enum write_mode { out_first, err_first, interleave, write_mode_last =3D interleave }; =20 +static const char * +write_mode_to_str (enum write_mode mode) +{ + switch (mode) + { + case out_first: return "out_first"; + case err_first: return "err_first"; + case interleave: return "interleave"; + default: return "write_mode_last"; + } +} + +static enum write_mode +str_to_write_mode (const char *mode) +{ + if (strcmp (mode, "out_first") =3D=3D 0) + return out_first; + else if (strcmp (mode, "err_first") =3D=3D 0) + return err_first; + else if (strcmp (mode, "interleave") =3D=3D 0) + return interleave; + return write_mode_last; +} + /* Describe what to write in the subprocess. */ struct test { @@ -52,11 +88,9 @@ struct test int status; }; =20 -/* For use with support_capture_subprocess. */ -static void -callback (void *closure) +_Noreturn static void +test_common (const struct test *test) { - const struct test *test =3D closure; bool mode_ok =3D false; switch (test->write_mode) { @@ -95,6 +129,40 @@ callback (void *closure) exit (test->status); } =20 +static int +parse_int (const char *str) +{ + char *endptr; + long int ret =3D strtol (str, &endptr, 10); + TEST_COMPARE (errno, 0); + TEST_VERIFY (ret >=3D 0 && ret <=3D INT_MAX); + return ret; +} + +/* For use with support_capture_subprogram. */ +_Noreturn static void +handle_restart (char *out, char *err, const char *write_mode, + const char *signal, const char *status) +{ + struct test test =3D + { + out, + err, + str_to_write_mode (write_mode), + parse_int (signal), + parse_int (status) + }; + test_common (&test); +} + +/* For use with support_capture_subprocess. */ +_Noreturn static void +callback (void *closure) +{ + const struct test *test =3D closure; + test_common (test); +} + /* Create a heap-allocated random string of letters. */ static char * random_string (size_t length) @@ -130,12 +198,59 @@ check_stream (const char *what, const struct xmemst= ream *stream, } } =20 +static struct support_capture_subprocess +do_subprocess (struct test *test) +{ + return support_capture_subprocess (callback, test); +} + +static struct support_capture_subprocess +do_subprogram (const struct test *test) +{ + /* Three digits per byte plus null terminator. */ + char signalstr[3 * sizeof(int) + 1]; + snprintf (signalstr, sizeof (signalstr), "%d", test->signal); + char statusstr[3 * sizeof(int) + 1]; + snprintf (statusstr, sizeof (statusstr), "%d", test->status); + + int argc =3D 0; + enum { + /* 4 elements from initial_argv (path to ld.so, '--library-path', th= e + path', and application name'), 2 for restart argument ('--direct'= , + '--restart'), 5 arguments plus NULL. */ + argv_size =3D 12 + }; + char *args[argv_size]; + + for (char **arg =3D initial_argv; *arg !=3D NULL; arg++) + args[argc++] =3D *arg; + + args[argc++] =3D (char*) "--direct"; + args[argc++] =3D (char*) "--restart"; + + args[argc++] =3D test->out; + args[argc++] =3D test->err; + args[argc++] =3D (char*) write_mode_to_str (test->write_mode); + args[argc++] =3D signalstr; + args[argc++] =3D statusstr; + args[argc] =3D NULL; + TEST_VERIFY (argc < argv_size); + + return support_capture_subprogram (args[0], args); +} + +enum test_type +{ + subprocess, + subprogram, +}; + static int -do_test (void) +do_multiple_tests (enum test_type type) { const int lengths[] =3D {0, 1, 17, 512, 20000, -1}; =20 - /* Test multiple combinations of support_capture_subprocess. + /* Test multiple combinations of support_capture_sub{process,program}. =20 length_idx_stdout: Index into the lengths array above, controls how many bytes are written by the subprocess to @@ -164,8 +279,10 @@ do_test (void) TEST_VERIFY (strlen (test.out) =3D=3D lengths[length_idx_s= tdout]); TEST_VERIFY (strlen (test.err) =3D=3D lengths[length_idx_s= tderr]); =20 - struct support_capture_subprocess result - =3D support_capture_subprocess (callback, &test); + struct support_capture_subprocess result + =3D type =3D=3D subprocess ? do_subprocess (&test) + : do_subprogram (&test); + check_stream ("stdout", &result.out, test.out); check_stream ("stderr", &result.err, test.err); if (test.signal !=3D 0) @@ -185,4 +302,54 @@ do_test (void) return 0; } =20 +static int +do_test (int argc, char *argv[]) +{ + /* We must have either: + + - one or four parameters if called initially: + + argv[1]: path for ld.so optional + + argv[2]: "--library-path" optional + + argv[3]: the library path optional + + argv[4]: the application name + + - six parameters left if called through re-execution: + + argv[1]: the application name + + argv[2]: the stdout to print + + argv[3]: the stderr to print + + argv[4]: the write mode to use + + argv[5]: the signal to issue + + argv[6]: the exit status code to use + + * When built with --enable-hardcoded-path-in-tests or issued withou= t + using the loader directly. + */ + + if (argc !=3D (restart ? 6 : 5) && argc !=3D (restart ? 6 : 2)) + FAIL_EXIT1 ("wrong number of arguments (%d)", argc); + + if (restart) + { + handle_restart (argv[1], /* stdout */ + argv[2], /* stderr */ + argv[3], /* write_mode */ + argv[4], /* signal */ + argv[5]); /* status */ + } + + initial_argv[0] =3D argv[1]; /* path for ld.so */ + initial_argv[1] =3D argv[2]; /* "--library-path" */ + initial_argv[2] =3D argv[3]; /* the library path */ + initial_argv[3] =3D argv[4]; /* the application name */ + initial_argv[4] =3D NULL; + + do_multiple_tests (subprocess); + do_multiple_tests (subprogram); + + return 0; +} + +#define CMDLINE_OPTIONS \ + { "restart", no_argument, &restart, 1 }, +#define TEST_FUNCTION_ARGV do_test #include diff --git a/support/xposix_spawn.c b/support/xposix_spawn.c new file mode 100644 index 0000000000..e846017632 --- /dev/null +++ b/support/xposix_spawn.c @@ -0,0 +1,32 @@ +/* xposix_spawn implementation. + Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include + +pid_t +xposix_spawn (const char *file, const posix_spawn_file_actions_t *fa, + const posix_spawnattr_t *attr, char *const args[], + char *const envp[]) +{ + pid_t pid; + int status =3D posix_spawn (&pid, file, fa, attr, args, envp); + if (status !=3D 0) + FAIL_EXIT1 ("posix_spawn to %s file failed: %m", file); + return pid; +} diff --git a/support/xposix_spawn_file_actions_addclose.c b/support/xposi= x_spawn_file_actions_addclose.c new file mode 100644 index 0000000000..eed54a6514 --- /dev/null +++ b/support/xposix_spawn_file_actions_addclose.c @@ -0,0 +1,29 @@ +/* xposix_spawn_file_actions_addclose implementation. + Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include + +int +xposix_spawn_file_actions_addclose (posix_spawn_file_actions_t *fa, int = fd) +{ + int status =3D posix_spawn_file_actions_addclose (fa, fd); + if (status =3D=3D -1) + FAIL_EXIT1 ("posix_spawn_file_actions_addclose failed: %m\n"); + return status; +} diff --git a/support/xposix_spawn_file_actions_adddup2.c b/support/xposix= _spawn_file_actions_adddup2.c new file mode 100644 index 0000000000..a43b6490be --- /dev/null +++ b/support/xposix_spawn_file_actions_adddup2.c @@ -0,0 +1,30 @@ +/* xposix_spawn_file_actions_adddup2 implementation. + Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include + +int +xposix_spawn_file_actions_adddup2 (posix_spawn_file_actions_t *fa, int f= d, + int newfd) +{ + int status =3D posix_spawn_file_actions_adddup2 (fa, fd, newfd); + if (status =3D=3D -1) + FAIL_EXIT1 ("posix_spawn_file_actions_adddup2 failed: %m\n"); + return status; +} diff --git a/support/xspawn.h b/support/xspawn.h new file mode 100644 index 0000000000..bbf89132e4 --- /dev/null +++ b/support/xspawn.h @@ -0,0 +1,34 @@ +/* posix_spawn with support checks. + Copyright (C) 2019 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef SUPPORT_XSPAWN_H +#define SUPPORT_XSPAWN_H + +#include + +__BEGIN_DECLS + +int xposix_spawn_file_actions_addclose (posix_spawn_file_actions_t *, in= t); +int xposix_spawn_file_actions_adddup2 (posix_spawn_file_actions_t *, int= , int); + +pid_t xposix_spawn (const char *, const posix_spawn_file_actions_t *, + const posix_spawnattr_t *, char *const [], char *const []); + +__END_DECLS + +#endif --=20 2.29.2