ソースを参照

Allow redirection of STDERR when starting processes.

Sree Harsha Totakura 10 年 前
コミット
2a35e345a2

+ 1 - 1
src/core/test_core_api.c

@@ -301,7 +301,7 @@ setup_peer (struct PeerContext *p, const char *cfgname)
   p->cfg = GNUNET_CONFIGURATION_create ();
   p->arm_proc =
     GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
-			     NULL, NULL,
+			     NULL, NULL, NULL,
 			     binary,
 			     "gnunet-service-arm",
                                "-c", cfgname, NULL);

+ 5 - 3
src/core/test_core_api_reliability.c

@@ -419,9 +419,11 @@ setup_peer (struct PeerContext *p, const char *cfgname)
   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
   p->cfg = GNUNET_CONFIGURATION_create ();
   p->arm_proc =
-    GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, binary,
-                               "gnunet-service-arm",
-                               "-c", cfgname, NULL);
+    GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                             NULL, NULL, NULL,
+                             binary,
+                             "gnunet-service-arm",
+                             "-c", cfgname, NULL);
   GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));
   p->th = GNUNET_TRANSPORT_connect (p->cfg, NULL, p, NULL, NULL, NULL);
   GNUNET_assert (p->th != NULL);

+ 1 - 1
src/core/test_core_api_start_only.c

@@ -134,7 +134,7 @@ setup_peer (struct PeerContext *p, const char *cfgname)
   p->cfg = GNUNET_CONFIGURATION_create ();
   p->arm_proc =
     GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
-			     NULL, NULL,
+			     NULL, NULL, NULL,
 			     binary,
 			     "gnunet-service-arm",
 			     "-c", cfgname, NULL);

+ 5 - 3
src/core/test_core_quota_compliance.c

@@ -571,9 +571,11 @@ setup_peer (struct PeerContext *p, const char *cfgname)
   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
   p->cfg = GNUNET_CONFIGURATION_create ();
   p->arm_proc =
-    GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, binary,
-                               "gnunet-service-arm",
-                               "-c", cfgname, NULL);
+    GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, 
+                             NULL, NULL, NULL,
+                             binary,
+                             "gnunet-service-arm",
+                             "-c", cfgname, NULL);
   GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));
   p->stats = GNUNET_STATISTICS_create ("core", p->cfg);
   GNUNET_assert (p->stats != NULL);

+ 1 - 1
src/fs/gnunet-auto-share.c

@@ -488,7 +488,7 @@ work (void *cls,
 	      _("Publishing `%s'\n"),
 	      wi->filename);
   publish_proc = GNUNET_OS_start_process_vap (GNUNET_YES,
-                                              0, NULL, NULL,
+                                              0, NULL, NULL, NULL,
 					      "gnunet-publish",
 					      argv);
   if (NULL == publish_proc)

+ 5 - 2
src/gns/gnunet-gns-import.c

@@ -129,8 +129,11 @@ run_process_and_wait (int pipe_control,
   va_end (apc2);
   if (arglen > 0)
     argp[-1] = '\0';
-  p = GNUNET_OS_start_process_va (pipe_control, std_inheritance, pipe_stdin,
-      pipe_stdout, filename, ap);
+  p = GNUNET_OS_start_process_va (pipe_control, std_inheritance,
+                                  pipe_stdin,
+                                  pipe_stdout,
+                                  NULL,
+                                  filename, ap);
   va_end (ap);
   if (NULL == p)
   {

+ 1 - 0
src/gns/test_gns_proxy.c

@@ -401,6 +401,7 @@ run (void *cls,
                                         GNUNET_OS_INHERIT_STD_ALL,
                                         NULL,
                                         NULL,
+                                        NULL,
                                         "gnunet-gns-proxy",
                                         "gnunet-gns-proxy",
                                         "-c", tmp_cfgfile, NULL);

+ 5 - 3
src/hostlist/test_gnunet_daemon_hostlist.c

@@ -135,9 +135,11 @@ setup_peer (struct PeerContext *p, const char *cfgname)
   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
   p->cfg = GNUNET_CONFIGURATION_create ();
   p->arm_proc =
-    GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, binary,
-                               "gnunet-service-arm",
-                               "-c", cfgname, NULL);
+    GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                             NULL, NULL, NULL,
+                             binary,
+                             "gnunet-service-arm",
+                             "-c", cfgname, NULL);
   GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));
   p->th =
       GNUNET_TRANSPORT_connect (p->cfg, NULL, p, NULL, &notify_connect, NULL);

+ 8 - 4
src/hostlist/test_gnunet_daemon_hostlist_learning.c

@@ -385,9 +385,11 @@ setup_learn_peer (struct PeerContext *p, const char *cfgname)
   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
   p->cfg = GNUNET_CONFIGURATION_create ();
   p->arm_proc =
-    GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, binary,
-                               "gnunet-service-arm",
-                               "-c", cfgname, NULL);
+    GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                             NULL, NULL, NULL,
+                             binary,
+                             "gnunet-service-arm",
+                             "-c", cfgname, NULL);
   GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));
   if (GNUNET_OK ==
       GNUNET_CONFIGURATION_get_value_string (p->cfg, "HOSTLIST", "HOSTLISTFILE",
@@ -420,7 +422,9 @@ setup_adv_peer (struct PeerContext *p, const char *cfgname)
   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
   p->cfg = GNUNET_CONFIGURATION_create ();
   p->arm_proc =
-    GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, binary,
+    GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                             NULL, NULL, NULL,
+                             binary,
 			     "gnunet-service-arm",
 			     "-c", cfgname, NULL);
   GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));

+ 5 - 3
src/hostlist/test_gnunet_daemon_hostlist_reconnect.c

@@ -135,9 +135,11 @@ setup_peer (struct PeerContext *p, const char *cfgname)
   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
   p->cfg = GNUNET_CONFIGURATION_create ();
   p->arm_proc =
-    GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, binary,
-                               "gnunet-service-arm",
-                               "-c", cfgname, NULL);
+    GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                             NULL, NULL, NULL,
+                             binary,
+                             "gnunet-service-arm",
+                             "-c", cfgname, NULL);
   GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));
   p->th =
       GNUNET_TRANSPORT_connect (p->cfg, NULL, p, NULL, &notify_connect, NULL);

+ 6 - 0
src/include/gnunet_os_lib.h

@@ -310,6 +310,7 @@ GNUNET_OS_process_get_pid (struct GNUNET_OS_Process *proc);
  * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags
  * @param pipe_stdin pipe to use to send input to child process (or NULL)
  * @param pipe_stdout pipe to use to get output from child process (or NULL)
+ * @param pipe_stderr pipe to use to get error output from child process (or NULL)
  * @param filename name of the binary
  * @param argv NULL-terminated array of arguments to the process
  * @return pointer to process structure of the new process, NULL on error
@@ -319,6 +320,7 @@ GNUNET_OS_start_process_vap (int pipe_control,
                              enum GNUNET_OS_InheritStdioFlags std_inheritance,
 			     struct GNUNET_DISK_PipeHandle *pipe_stdin,
 			     struct GNUNET_DISK_PipeHandle *pipe_stdout,
+			     struct GNUNET_DISK_PipeHandle *pipe_stderr,
 			     const char *filename,
 			     char *const argv[]);
 
@@ -330,6 +332,7 @@ GNUNET_OS_start_process_vap (int pipe_control,
  * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags
  * @param pipe_stdin pipe to use to send input to child process (or NULL)
  * @param pipe_stdout pipe to use to get output from child process (or NULL)
+ * @param pipe_stderr pipe to use to get error output from child process (or NULL)
  * @param filename name of the binary
  * @param ... NULL-terminated list of arguments to the process
  * @return pointer to process structure of the new process, NULL on error
@@ -339,6 +342,7 @@ GNUNET_OS_start_process (int pipe_control,
                          enum GNUNET_OS_InheritStdioFlags std_inheritance,
 			 struct GNUNET_DISK_PipeHandle *pipe_stdin,
                          struct GNUNET_DISK_PipeHandle *pipe_stdout,
+                         struct GNUNET_DISK_PipeHandle *pipe_stderr,
                          const char *filename, ...);
 
 
@@ -349,6 +353,7 @@ GNUNET_OS_start_process (int pipe_control,
  * @param std_inheritance a set of GNUNET_OS_INHERIT_STD_* flags
  * @param pipe_stdin pipe to use to send input to child process (or NULL)
  * @param pipe_stdout pipe to use to get output from child process (or NULL)
+ * @param pipe_stderr pipe to use to get error output from child process (or NULL)
  * @param filename name of the binary
  * @param va NULL-terminated list of arguments to the process
  * @return pointer to process structure of the new process, NULL on error
@@ -358,6 +363,7 @@ GNUNET_OS_start_process_va (int pipe_control,
                             enum GNUNET_OS_InheritStdioFlags std_inheritance,
 			    struct GNUNET_DISK_PipeHandle *pipe_stdin,
                             struct GNUNET_DISK_PipeHandle *pipe_stdout,
+                            struct GNUNET_DISK_PipeHandle *pipe_stderr,
                             const char *filename, va_list va);
 
 /**

+ 2 - 2
src/nat/nat.c

@@ -907,7 +907,7 @@ start_gnunet_nat_server (struct GNUNET_NAT_Handle *h)
     /* Start the server process */
     binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-server");
     h->server_proc =
-        GNUNET_OS_start_process (GNUNET_NO, 0, NULL, h->server_stdout,
+        GNUNET_OS_start_process (GNUNET_NO, 0, NULL, h->server_stdout, NULL,
                                  binary,
                                  "gnunet-helper-nat-server",
                                  h->internal_address, NULL);
@@ -1445,7 +1445,7 @@ GNUNET_NAT_run_client (struct GNUNET_NAT_Handle *h,
        (unsigned int) h->adv_port);
   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-helper-nat-client");
   proc =
-      GNUNET_OS_start_process (GNUNET_NO, 0, NULL, NULL,
+      GNUNET_OS_start_process (GNUNET_NO, 0, NULL, NULL, NULL,
                                binary,
                                "gnunet-helper-nat-client",
                                h->internal_address,

+ 2 - 2
src/nat/nat_mini.c

@@ -213,8 +213,8 @@ GNUNET_NAT_mini_get_external_ipv4 (struct GNUNET_TIME_Relative timeout,
     return eh;
   }
   eh->eip =
-    GNUNET_OS_start_process (GNUNET_NO, 0, NULL, eh->opipe,
-                             "external-ip", "external-ip",
+      GNUNET_OS_start_process (GNUNET_NO, 0, NULL, eh->opipe, NULL,
+                               "external-ip", "external-ip",
                                NULL);
   if (NULL == eh->eip)
   {

+ 2 - 1
src/nat/test_nat_test.c

@@ -107,7 +107,8 @@ main (int argc, char *const argv[])
 
   gns = GNUNET_OS_start_process (GNUNET_YES,
                                  GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
-                                 NULL, NULL, "gnunet-nat-server",
+                                 NULL, NULL, NULL,
+                                 "gnunet-nat-server",
                                  "gnunet-nat-server",
                                  "-c", "test_nat_test_data.conf",
                                  "12345", NULL);

+ 4 - 2
src/statistics/test_statistics_api.c

@@ -146,7 +146,8 @@ main (int argc, char *argv_ign[])
                     NULL);
   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-statistics");
   proc =
-      GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL,
+      GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                               NULL, NULL, NULL,
 			       binary,
                                "gnunet-service-statistics",
                                "-c", "test_statistics_api_data.conf", NULL);
@@ -169,7 +170,8 @@ main (int argc, char *argv_ign[])
   ok = 1;
   /* restart to check persistence! */
   proc =
-      GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL,
+      GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                               NULL, NULL, NULL,
 			       binary,
                                "gnunet-service-statistics",
                                "-c", "test_statistics_api_data.conf", NULL);

+ 1 - 1
src/statistics/test_statistics_api_loop.c

@@ -94,7 +94,7 @@ main (int argc, char *argv_ign[])
   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-statistics");
   proc =
     GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
-			     NULL, NULL,
+			     NULL, NULL, NULL,
 			     binary,
 			     "gnunet-service-statistics",
 			     "-c", "test_statistics_api_data.conf", NULL);

+ 2 - 1
src/statistics/test_statistics_api_watch.c

@@ -122,7 +122,8 @@ main (int argc, char *argv_ign[])
 
   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-statistics");
   proc =
-    GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL,
+    GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                             NULL, NULL, NULL,
 			     binary,
 			     "gnunet-service-statistics",
 			     "-c", "test_statistics_api_data.conf", NULL);

+ 2 - 1
src/statistics/test_statistics_api_watch_zero_value.c

@@ -157,7 +157,8 @@ main (int argc, char *argv_ign[])
 
   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-statistics");
   proc =
-    GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL,
+    GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                             NULL, NULL, NULL,
 			     binary,
 			     "gnunet-service-statistics",
 			     "-c", "test_statistics_api_data.conf", NULL);

+ 3 - 2
src/testbed/gnunet-helper-testbed.c

@@ -461,8 +461,9 @@ tokenizer_cb (void *cls, void *client,
   }
   testbed =
       GNUNET_OS_start_process (PIPE_CONTROL,
-                               GNUNET_OS_INHERIT_STD_ERR /*verbose? */ , NULL,
-                               NULL, binary, "gnunet-service-testbed", "-c",
+                               GNUNET_OS_INHERIT_STD_ERR /*verbose? */ ,
+                               NULL, NULL, NULL,
+                               binary, "gnunet-service-testbed", "-c",
                                config, NULL);
   GNUNET_free (binary);
   GNUNET_free (config);

+ 1 - 1
src/testbed/gnunet_mpi_test.c

@@ -70,7 +70,7 @@ main (int argc, char *argv[])
     argv2[cnt - 1] = argv[cnt];
   proc =
       GNUNET_OS_start_process_vap (GNUNET_NO, GNUNET_OS_INHERIT_STD_ALL, NULL,
-                                   NULL, argv2[0], argv2);
+                                   NULL, NULL, argv2[0], argv2);
   if (NULL == proc)
   {
     printf ("Cannot exec\n");

+ 1 - 1
src/testbed/gnunet_testbed_mpi_spawn.c

@@ -246,7 +246,7 @@ run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   /* Spawn the new process here */
   LOG (GNUNET_ERROR_TYPE_INFO, _("Spawning process `%s'\n"), argv2[0]);
   child = GNUNET_OS_start_process_vap (GNUNET_NO, GNUNET_OS_INHERIT_STD_ALL, NULL,
-                                       NULL,
+                                       NULL, NULL,
                                        argv2[0], argv2);
   if (NULL == child)
   {

+ 1 - 1
src/testbed/testbed_api_hosts.c

@@ -1349,7 +1349,7 @@ GNUNET_TESTBED_is_host_habitable (const struct GNUNET_TESTBED_Host *host,
   free_argv (rsh_args);
   h->auxp =
       GNUNET_OS_start_process_vap (GNUNET_NO, GNUNET_OS_INHERIT_STD_ERR, NULL,
-                                   NULL, h->helper_argv[0], h->helper_argv);
+                                   NULL, NULL, h->helper_argv[0], h->helper_argv);
   if (NULL == h->auxp)
   {
     GNUNET_break (0);           /* Cannot exec SSH? */

+ 1 - 1
src/testing/testing.c

@@ -491,7 +491,7 @@ start_shared_service_instance (struct SharedServiceInstance *i)
   GNUNET_free (binary);
   i->proc = GNUNET_OS_start_process (PIPE_CONTROL,
                                      GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
-                                     NULL, NULL,
+                                     NULL, NULL, NULL,
                                      libexec_binary,
                                      libexec_binary,
                                      "-c",

+ 6 - 2
src/transport/gnunet-transport-certificate-creation.c

@@ -94,7 +94,9 @@ main (int argc, char **argv)
   /* Create RSA Private Key */
   /* openssl genrsa -out $1 1024 2> /dev/null */
   openssl =
-      GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, "openssl", "openssl", "genrsa",
+      GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                               NULL, NULL, NULL,
+                               "openssl", "openssl", "genrsa",
                                "-out", argv[1], "1024", NULL);
   if (NULL == openssl)
   {
@@ -108,7 +110,9 @@ main (int argc, char **argv)
   /* Create a self-signed certificate in batch mode using rsa key */
   /* openssl req -batch -days 365 -out $2 -new -x509 -key $1 2> /dev/null */
   openssl =
-      GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, "openssl", "openssl", "req",
+      GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                               NULL, NULL, NULL,
+                               "openssl", "openssl", "req",
                                "-batch", "-days", "365", "-out", argv[2],
                                "-new", "-x509", "-key", argv[1], NULL);
   if (NULL == openssl)

+ 4 - 2
src/transport/gnunet-transport.c

@@ -665,8 +665,10 @@ do_test_configuration (const struct GNUNET_CONFIGURATION_Handle *cfg)
     {
       binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-resolver");
       resolver = GNUNET_OS_start_process (GNUNET_YES,
-          GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL, binary,
-          "gnunet-service-resolver", NULL );
+                                          GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                                          NULL, NULL, NULL,
+                                          binary,
+                                          "gnunet-service-resolver", NULL );
       GNUNET_free(binary);
     }
     resolver_users++;

+ 2 - 1
src/transport/plugin_transport_http_server.c

@@ -1946,7 +1946,8 @@ server_load_certificate (struct HTTP_Server_Plugin *plugin)
                 "No usable TLS certificate found, creating certificate\n");
     errno = 0;
     cert_creation =
-        GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, NULL,
+        GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                                 NULL, NULL, NULL,
                                  "gnunet-transport-certificate-creation",
                                  "gnunet-transport-certificate-creation",
                                  key_file, cert_file, NULL);

+ 1 - 1
src/util/gnunet-uri.c

@@ -113,7 +113,7 @@ run (void *cls, char *const *args, const char *cfgfile,
 								GNUNET_DISK_PIPE_END_READ),
 				       &maint_child_death, NULL);
   p = GNUNET_OS_start_process (GNUNET_NO, 0,
-			       NULL, NULL,
+			       NULL, NULL, NULL,
 			       program,
 			       program,
 			       args[0],

+ 1 - 1
src/util/helper.c

@@ -426,7 +426,7 @@ start_helper (struct GNUNET_HELPER_Handle *h)
       GNUNET_DISK_pipe_handle (h->helper_in, GNUNET_DISK_PIPE_END_WRITE);
   h->helper_proc =
     GNUNET_OS_start_process_vap (h->with_control_pipe, GNUNET_OS_INHERIT_STD_ERR,
-				 h->helper_in, h->helper_out,
+				 h->helper_in, h->helper_out, NULL,
 				 h->binary_name,
 				 h->binary_argv);
   if (NULL == h->helper_proc)

+ 38 - 4
src/util/os_priority.c

@@ -503,6 +503,7 @@ start_process (int pipe_control,
                enum GNUNET_OS_InheritStdioFlags std_inheritance,
 	       struct GNUNET_DISK_PipeHandle *pipe_stdin,
 	       struct GNUNET_DISK_PipeHandle *pipe_stdout,
+	       struct GNUNET_DISK_PipeHandle *pipe_stderr,
 	       const SOCKTYPE *lsocks,
 	       const char *filename,
 	       char *const argv[])
@@ -523,6 +524,8 @@ start_process (int pipe_control,
   unsigned int ls;
   int fd_stdout_write;
   int fd_stdout_read;
+  int fd_stderr_write;
+  int fd_stderr_read;
   int fd_stdin_read;
   int fd_stdin_write;
 
@@ -583,6 +586,19 @@ start_process (int pipe_control,
 						      (pipe_stdin, GNUNET_DISK_PIPE_END_WRITE),
 						      &fd_stdin_write, sizeof (int)));
   }
+  if (NULL != pipe_stderr)
+  {
+    GNUNET_assert (GNUNET_OK ==
+                   GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle
+                                                      (pipe_stderr,
+                                                       GNUNET_DISK_PIPE_END_READ),
+                                                      &fd_stderr_read, sizeof (int)));
+    GNUNET_assert (GNUNET_OK ==
+                   GNUNET_DISK_internal_file_handle_ (GNUNET_DISK_pipe_handle
+                                                      (pipe_stderr,
+                                                       GNUNET_DISK_PIPE_END_WRITE),
+                                                      &fd_stderr_write, sizeof (int)));
+  }
   lscp = NULL;
   ls = 0;
   if (NULL != lsocks)
@@ -659,7 +675,14 @@ start_process (int pipe_control,
     GNUNET_break (0 == close (1));
     open_dev_null (1, O_WRONLY);
   }
-  if (0 == (std_inheritance & GNUNET_OS_INHERIT_STD_ERR))
+  if (NULL != pipe_stderr)
+  {
+    GNUNET_break (0 == close (fd_stderr_read));
+    if (-1 == dup2 (fd_stderr_write, 2))
+      LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "dup2");
+    GNUNET_break (0 == close (fd_stderr_write));
+  }
+  else if (0 == (std_inheritance & GNUNET_OS_INHERIT_STD_ERR))
   {
     GNUNET_break (0 == close (2));
     open_dev_null (2, O_WRONLY);
@@ -1220,6 +1243,7 @@ GNUNET_OS_start_process_vap (int pipe_control,
                              enum GNUNET_OS_InheritStdioFlags std_inheritance,
 			     struct GNUNET_DISK_PipeHandle *pipe_stdin,
 			     struct GNUNET_DISK_PipeHandle *pipe_stdout,
+                             struct GNUNET_DISK_PipeHandle *pipe_stderr,
 			     const char *filename,
 			     char *const argv[])
 {
@@ -1227,6 +1251,7 @@ GNUNET_OS_start_process_vap (int pipe_control,
                         std_inheritance,
 			pipe_stdin,
 			pipe_stdout,
+                        pipe_stderr,
 			NULL,
 			filename,
 			argv);
@@ -1249,6 +1274,7 @@ GNUNET_OS_start_process_va (int pipe_control,
                             enum GNUNET_OS_InheritStdioFlags std_inheritance,
 			    struct GNUNET_DISK_PipeHandle *pipe_stdin,
                             struct GNUNET_DISK_PipeHandle *pipe_stdout,
+                            struct GNUNET_DISK_PipeHandle *pipe_stderr,
                             const char *filename, va_list va)
 {
   struct GNUNET_OS_Process *ret;
@@ -1271,6 +1297,7 @@ GNUNET_OS_start_process_va (int pipe_control,
                                      std_inheritance,
 				     pipe_stdin,
 				     pipe_stdout,
+                                     pipe_stderr,
 				     filename,
 				     argv);
   GNUNET_free (argv);
@@ -1294,14 +1321,20 @@ GNUNET_OS_start_process (int pipe_control,
                          enum GNUNET_OS_InheritStdioFlags std_inheritance,
 			 struct GNUNET_DISK_PipeHandle *pipe_stdin,
                          struct GNUNET_DISK_PipeHandle *pipe_stdout,
+                         struct GNUNET_DISK_PipeHandle *pipe_stderr,
                          const char *filename, ...)
 {
   struct GNUNET_OS_Process *ret;
   va_list ap;
 
   va_start (ap, filename);
-  ret = GNUNET_OS_start_process_va (pipe_control, std_inheritance, pipe_stdin,
-				    pipe_stdout, filename, ap);
+  ret = GNUNET_OS_start_process_va (pipe_control,
+                                    std_inheritance,
+                                    pipe_stdin,
+				    pipe_stdout,
+                                    pipe_stderr,
+                                    filename,
+                                    ap);
   va_end (ap);
   return ret;
 }
@@ -1332,6 +1365,7 @@ GNUNET_OS_start_process_v (int pipe_control,
                         std_inheritance,
 			NULL,
 			NULL,
+                        NULL,
 			lsocks,
 			filename,
 			argv);
@@ -1776,7 +1810,7 @@ GNUNET_OS_command_run (GNUNET_OS_LineProcessor proc, void *proc_cls,
     return NULL;
   va_start (ap, binary);
   /* redirect stdout, don't inherit stderr/stdin */
-  eip = GNUNET_OS_start_process_va (GNUNET_NO, 0, NULL, opipe, binary, ap);
+  eip = GNUNET_OS_start_process_va (GNUNET_NO, 0, NULL, opipe, NULL, binary, ap);
   va_end (ap);
   if (NULL == eip)
   {

+ 2 - 1
src/util/test_common_logging_runtime_loglevels.c

@@ -391,7 +391,8 @@ runone ()
     break;
   }
 
-  proc = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, NULL, pipe_stdout,
+  proc = GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                                  NULL, pipe_stdout, NULL,
 #if MINGW
                                   "test_common_logging_dummy",
 #else

+ 8 - 3
src/util/test_os_start_process.c

@@ -135,7 +135,8 @@ run_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 
   proc =
       GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_ERR,
-                               hello_pipe_stdin, hello_pipe_stdout, fn,
+                               hello_pipe_stdin, hello_pipe_stdout, NULL,
+                               fn,
                                "test_gnunet_echo_hello", "-", NULL);
   GNUNET_free (fn);
 
@@ -203,7 +204,9 @@ check_kill ()
   }
   fn = GNUNET_OS_get_libexec_binary_path ("gnunet-service-resolver");
   proc =
-    GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_ERR, hello_pipe_stdin, hello_pipe_stdout, fn,
+    GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_ERR,
+                             hello_pipe_stdin, hello_pipe_stdout, NULL,
+                             fn,
 			     "gnunet-service-resolver", "-", NULL);
   sleep (1); /* give process time to start, so we actually use the pipe-kill mechanism! */
   GNUNET_free (fn);
@@ -234,7 +237,9 @@ check_instant_kill ()
   }
   fn = GNUNET_OS_get_libexec_binary_path ("gnunet-service-resolver");
   proc =
-    GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_ERR, hello_pipe_stdin, hello_pipe_stdout, fn,
+    GNUNET_OS_start_process (GNUNET_YES, GNUNET_OS_INHERIT_STD_ERR,
+                             hello_pipe_stdin, hello_pipe_stdout, NULL,
+                             fn,
 			     "gnunet-service-resolver", "-", NULL);
   if (0 != GNUNET_OS_process_kill (proc, GNUNET_TERM_SIG))
   {

+ 2 - 1
src/util/test_resolver_api.c

@@ -367,7 +367,8 @@ main (int argc, char *argv[])
   fn = GNUNET_OS_get_libexec_binary_path ("gnunet-service-resolver");
   proc = GNUNET_OS_start_process (GNUNET_YES,
 				  GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
-				  NULL, NULL, fn,
+				  NULL, NULL, NULL,
+                                  fn,
 				  "gnunet-service-resolver",
                                   "-c", "test_resolver_api_data.conf", NULL);
   GNUNET_assert (NULL != proc);