From 5dec45de0465e2eb483c3df18773c0501992e183 Mon Sep 17 00:00:00 2001 From: "Nathan S. Evans" Date: Tue, 16 Feb 2010 12:10:29 +0000 Subject: [PATCH] start process change to allow stdout to be sent from child process --- src/util/Makefile.am | 8 ++++- src/util/disk.c | 75 ++++++++++++++++++++++++++++++++++++++---- src/util/os_priority.c | 43 ++++++++++++++++-------- 3 files changed, 105 insertions(+), 21 deletions(-) diff --git a/src/util/Makefile.am b/src/util/Makefile.am index 4cae7b19d..99cb0af97 100644 --- a/src/util/Makefile.am +++ b/src/util/Makefile.am @@ -142,7 +142,8 @@ check_PROGRAMS = \ test_service \ test_strings \ test_time \ - perf_crypto_hash + perf_crypto_hash \ + test_os_start_process TESTS = $(check_SCRIPTS) $(check_PROGRAMS) @@ -153,6 +154,11 @@ test_bio_LDADD = \ $(top_builddir)/src/util/libgnunetutil.la +test_os_start_process_SOURCES = \ + test_os_start_process.c +test_os_start_process_LDADD = \ + $(top_builddir)/src/util/libgnunetutil.la + test_client_SOURCES = \ test_client.c test_client_LDADD = \ diff --git a/src/util/disk.c b/src/util/disk.c index 8e90a44e5..710935516 100644 --- a/src/util/disk.c +++ b/src/util/disk.c @@ -1671,6 +1671,62 @@ GNUNET_DISK_pipe (int blocking) } +/** + * Closes an interprocess channel + * + * @param p pipe to close + * @return GNUNET_OK on success, GNUNET_SYSERR otherwise + */ +int +GNUNET_DISK_pipe_close_end (struct GNUNET_DISK_PipeHandle *p, enum GNUNET_DISK_PipeEnd end) +{ + int ret = GNUNET_OK; + int save; + + /* FIXME: What can we safely set HANDLE to once we've closed an end, NULL? */ +#ifdef MINGW + if (end == GNUNET_DISK_PIPE_END_READ) + { + if (!CloseHandle (p->fd[0]->h)) + { + SetErrnoFromWinError (GetLastError ()); + ret = GNUNET_SYSERR; + } + } + else if (end == GNUNET_DISK_PIPE_END_WRITE) + { + if (!CloseHandle (p->fd[1]->h)) + { + SetErrnoFromWinError (GetLastError ()); + ret = GNUNET_SYSERR; + } + } + save = errno; +#else + save = 0; + if (end == GNUNET_DISK_PIPE_END_READ) + { + if (0 != close (p->fd[0]->fd)) + { + ret = GNUNET_SYSERR; + save = errno; + } + p->fd[0]->fd = -1; + } + else if (end == GNUNET_DISK_PIPE_END_WRITE) + { + if (0 != close (p->fd[1]->fd)) + { + ret = GNUNET_SYSERR; + save = errno; + } + p->fd[1]->fd = -1; + } +#endif + errno = save; + return ret; +} + /** * Closes an interprocess channel * @@ -1697,15 +1753,22 @@ GNUNET_DISK_pipe_close (struct GNUNET_DISK_PipeHandle *p) save = errno; #else save = 0; - if (0 != close (p->fd[0]->fd)) + if (p->fd[0]->fd != -1) { - ret = GNUNET_SYSERR; - save = errno; + if (0 != close (p->fd[0]->fd)) + { + ret = GNUNET_SYSERR; + save = errno; + } } - if (0 != close (p->fd[1]->fd)) + + if (p->fd[1]->fd != -1) { - ret = GNUNET_SYSERR; - save = errno; + if (0 != close (p->fd[1]->fd)) + { + ret = GNUNET_SYSERR; + save = errno; + } } #endif GNUNET_free (p); diff --git a/src/util/os_priority.c b/src/util/os_priority.c index bd511a660..9820592ac 100644 --- a/src/util/os_priority.c +++ b/src/util/os_priority.c @@ -27,6 +27,7 @@ #include "platform.h" #include "gnunet_common.h" #include "gnunet_os_lib.h" +#include "disk.h" /** * Set process priority @@ -115,7 +116,6 @@ GNUNET_OS_set_process_priority (pid_t proc, return GNUNET_OK; } - /** * Start a process. * @@ -124,14 +124,31 @@ GNUNET_OS_set_process_priority (pid_t proc, * @return process ID of the new process, -1 on error */ pid_t -GNUNET_OS_start_process (const char *filename, ...) +GNUNET_OS_start_process (struct GNUNET_DISK_PipeHandle *pipe_stdin, struct GNUNET_DISK_PipeHandle *pipe_stdout, const char *filename, ...) { + /* FIXME: Make this work on windows!!! */ va_list ap; #ifndef MINGW pid_t ret; char **argv; int argc; + int fd_stdout_write; + int fd_stdin_read; + + argc = 0; + va_start (ap, filename); + while (NULL != va_arg (ap, char *)) + argc++; + va_end (ap); + argv = GNUNET_malloc (sizeof (char *) * (argc + 1)); + argc = 0; + va_start (ap, filename); + while (NULL != (argv[argc] = va_arg (ap, char *))) + argc++; + va_end (ap); + if (pipe_stdout != NULL) + GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle(pipe_stdout, GNUNET_DISK_PIPE_END_WRITE), &fd_stdout_write, sizeof (int)); #if HAVE_WORKING_VFORK ret = vfork (); @@ -156,21 +173,19 @@ GNUNET_OS_start_process (const char *filename, ...) /* let's give the child process a chance to run execvp, 1s should be plenty in practice */ sleep (1); + if (pipe_stdout != NULL) + GNUNET_DISK_pipe_close_end(pipe_stdout, GNUNET_DISK_PIPE_END_WRITE); #endif } + GNUNET_free (argv); return ret; } - argc = 0; - va_start (ap, filename); - while (NULL != va_arg (ap, char *)) - argc++; - va_end (ap); - argv = GNUNET_malloc (sizeof (char *) * (argc + 1)); - argc = 0; - va_start (ap, filename); - while (NULL != (argv[argc] = va_arg (ap, char *))) - argc++; - va_end (ap); + if (pipe_stdout != NULL) + { + dup2(fd_stdout_write, 1); + close (fd_stdout_write); + } + execvp (filename, argv); GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "execvp", filename); _exit (1); @@ -221,8 +236,8 @@ GNUNET_OS_start_process (const char *filename, ...) return proc.dwProcessId; #endif -} +} -- 2.25.1