1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-08-07 06:43:00 +03:00

support: Add support_capture_subprogram

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 <carlos@redhat.com>
This commit is contained in:
Adhemerval Zanella
2019-04-12 17:39:53 -03:00
parent bae8cf0e93
commit 0e16969129
11 changed files with 573 additions and 50 deletions

View File

@@ -16,6 +16,7 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <support/subprocess.h>
#include <support/capture_subprocess.h>
#include <errno.h>
@@ -23,6 +24,7 @@
#include <support/check.h>
#include <support/xunistd.h>
#include <support/xsocket.h>
#include <support/xspawn.h>
static void
transfer (const char *what, struct pollfd *pfd, struct xmemstream *stream)
@@ -50,6 +52,30 @@ transfer (const char *what, struct pollfd *pfd, struct xmemstream *stream)
}
}
static void
support_capture_poll (struct support_capture_subprocess *result,
struct support_subprocess *proc)
{
struct pollfd fds[2] =
{
{ .fd = proc->stdout_pipe[0], .events = POLLIN },
{ .fd = proc->stderr_pipe[0], .events = POLLIN },
};
do
{
xpoll (fds, 2, -1);
transfer ("stdout", &fds[0], &result->out);
transfer ("stderr", &fds[1], &result->err);
}
while (fds[0].events != 0 || fds[1].events != 0);
xfclose_memstream (&result->out);
xfclose_memstream (&result->err);
result->status = support_process_wait (proc);
}
struct support_capture_subprocess
support_capture_subprocess (void (*callback) (void *), void *closure)
{
@@ -57,52 +83,22 @@ support_capture_subprocess (void (*callback) (void *), void *closure)
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);
struct support_subprocess proc = support_subprocess (callback, closure);
TEST_VERIFY (fflush (stdout) == 0);
TEST_VERIFY (fflush (stderr) == 0);
support_capture_poll (&result, &proc);
return result;
}
pid_t pid = xfork ();
if (pid == 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 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 pollfd fds[2] =
{
{ .fd = stdout_pipe[0], .events = POLLIN },
{ .fd = stderr_pipe[0], .events = POLLIN },
};
struct support_subprocess proc = support_subprogram (file, argv);
do
{
xpoll (fds, 2, -1);
transfer ("stdout", &fds[0], &result.out);
transfer ("stderr", &fds[1], &result.err);
}
while (fds[0].events != 0 || fds[1].events != 0);
xclose (stdout_pipe[0]);
xclose (stderr_pipe[0]);
xfclose_memstream (&result.out);
xfclose_memstream (&result.err);
xwaitpid (pid, &result.status, 0);
support_capture_poll (&result, &proc);
return result;
}