[tor-commits] [tor/master] Generalize process spawning so its test compiles (but fails) in Windows

nickm at torproject.org nickm at torproject.org
Tue Aug 30 19:58:36 UTC 2011


commit 35c89be02b535e2951b695429bd9b255afb2a7b2
Author: Steven Murdoch <Steven.Murdoch at cl.cam.ac.uk>
Date:   Thu Jul 21 16:34:48 2011 +0100

    Generalize process spawning so its test compiles (but fails) in Windows
    
    - pid, stdout/stderr_pipe now encapsulated in process_handle
    - read_all replaced by tor_read_all_from_process_stdin/stderr
    - waitpid replaced by tor_get_exit_code
    
    Untested on *nix
---
 src/common/util.c    |   78 ++++++++++++++++++++++++++++++++++++++++++--------
 src/common/util.h    |   23 +++++++++++++-
 src/test/test_util.c |   33 +++++++++------------
 3 files changed, 101 insertions(+), 33 deletions(-)

diff --git a/src/common/util.c b/src/common/util.c
index b95ee3a..5bc7a80 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -2978,14 +2978,15 @@ format_helper_exit_status(unsigned char child_state, int saved_errno,
  * -1.  Some parts of this code are based on the POSIX subprocess module from
  * Python.
  */
-int
-tor_spawn_background(const char *const filename, int *stdout_read,
-                     int *stderr_read, const char **argv)
+process_handle_t
+tor_spawn_background(const char *const filename, const char **argv)
 {
+  process_handle_t process_handle;
 #ifdef MS_WINDOWS
-  (void) filename; (void) stdout_read; (void) stderr_read; (void) argv;
+  (void) filename; (void) argv;
   log_warn(LD_BUG, "not yet implemented on Windows.");
-  return -1;
+  process_handle.status = -1;
+  return process_handle;
 #else
   pid_t pid;
   int stdout_pipe[2];
@@ -3016,7 +3017,8 @@ tor_spawn_background(const char *const filename, int *stdout_read,
     log_warn(LD_GENERAL,
       "Failed to set up pipe for stdout communication with child process: %s",
        strerror(errno));
-    return -1;
+    process_handle.status = -1;
+    return process_handle;
   }
 
   retval = pipe(stderr_pipe);
@@ -3024,7 +3026,8 @@ tor_spawn_background(const char *const filename, int *stdout_read,
     log_warn(LD_GENERAL,
       "Failed to set up pipe for stderr communication with child process: %s",
       strerror(errno));
-    return -1;
+    process_handle.status = -1;
+    return process_handle;
   }
 
   child_state = CHILD_STATE_MAXFD;
@@ -3109,7 +3112,8 @@ tor_spawn_background(const char *const filename, int *stdout_read,
     (void) nbytes;
 
     _exit(255);
-    return -1; /* Never reached, but avoids compiler warning */
+    process_handle.status = -1;
+    return process_handle; /* Never reached, but avoids compiler warning */
   }
 
   /* In parent */
@@ -3120,11 +3124,12 @@ tor_spawn_background(const char *const filename, int *stdout_read,
     close(stdout_pipe[1]);
     close(stderr_pipe[0]);
     close(stderr_pipe[1]);
-    return -1;
+    process_handle.status = -1;
+    return process_handle;
   }
 
   /* Return read end of the pipes to caller, and close write end */
-  *stdout_read = stdout_pipe[0];
+  process_handle.stdout_pipe = stdout_pipe[0];
   retval = close(stdout_pipe[1]);
 
   if (-1 == retval) {
@@ -3135,7 +3140,7 @@ tor_spawn_background(const char *const filename, int *stdout_read,
        needs to know about the pid in order to reap it later */
   }
 
-  *stderr_read = stderr_pipe[0];
+  process_handle.stderr_pipe = stderr_pipe[0];
   retval = close(stderr_pipe[1]);
 
   if (-1 == retval) {
@@ -3146,7 +3151,56 @@ tor_spawn_background(const char *const filename, int *stdout_read,
        needs to know about the pid in order to reap it later */
   }
 
-  return pid;
+  process_handle.status = 0;
+  process_handle.pid = pid;
+  return process_handle;
+#endif
+}
+
+int
+tor_get_exit_code(const process_handle_t process_handle)
+{
+#ifdef MS_WINDOWS
+  log_warn(LD_BUG, "not yet implemented on Windows.");
+  return -1;
+#else
+  int stat_loc;
+
+  retval = waitpid(process_handle.pid, &stat_loc, 0);
+  if (retval != process_handle.pid) {
+    log_warn(LD_GENERAL, "waitpid() failed for PID %d: %s", process_handle.pid,
+             sterror(errno));
+    return -1;
+  }
+
+  if (!WIFEXITED(stat_loc)) {
+    log_warn(LD_GENERAL, "Process %d did not exit normally", process_handle.pid);
+    return -1;
+  }
+
+  return WEXITSTATUS(stat_loc);
+#endif // MS_WINDOWS
+}
+
+ssize_t
+tor_read_all_from_process_stdin(const process_handle_t process_handle,
+                                char *buf, size_t count)
+{
+#ifdef MS_WINDOWS
+  return -1;
+#else
+  return read_all(process_handle.stdin_pipe, buf, count, 0);
+#endif
+}
+  
+ssize_t
+tor_read_all_from_process_stderr(const process_handle_t process_handle,
+                                 char *buf, size_t count)
+{
+#ifdef MS_WINDOWS
+  return -1;
+#else
+  return read_all(process_handle.stderr_pipe, buf, count, 0);
 #endif
 }
 
diff --git a/src/common/util.h b/src/common/util.h
index 6496c42..2cf57a1 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -347,8 +347,27 @@ HANDLE load_windows_system_library(const TCHAR *library_name);
 
 #ifdef UTIL_PRIVATE
 /* Prototypes for private functions only used by util.c (and unit tests) */
-int tor_spawn_background(const char *const filename, int *stdout_read,
-                         int *stderr_read, const char **argv);
+
+typedef struct process_handle_s {
+  int status;
+#ifdef MS_WINDOWS
+  HANDLE stdout_pipe;
+  HANDLE stderr_pipe;
+  HANDLE pid;
+#else
+  int stdout_pipe;
+  int stderr_pipe;
+  int pid;
+#endif // MS_WINDOWS
+} process_handle_t;
+
+process_handle_t tor_spawn_background(const char *const filename,
+                                      const char **argv);
+int tor_get_exit_code(const process_handle_t pid);
+ssize_t tor_read_all_from_process_stdin(const process_handle_t process_handle,
+                                        char *buf, size_t count);
+ssize_t tor_read_all_from_process_stderr(const process_handle_t process_handle,
+                                         char *buf, size_t count);
 void format_helper_exit_status(unsigned char child_state,
                                int saved_errno, char *hex_errno);
 
diff --git a/src/test/test_util.c b/src/test/test_util.c
index c4769e6..fce53b8 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -1376,42 +1376,38 @@ test_util_fgets_eagain(void *ptr)
 }
 #endif
 
-#ifndef MS_WINDOWS
 /** Helper function for testing tor_spawn_background */
 static void
 run_util_spawn_background(const char *argv[], const char *expected_out,
                           const char *expected_err, int expected_exit)
 {
-  int stdout_pipe=-1, stderr_pipe=-1;
-  int retval, stat_loc;
-  pid_t pid;
+  int retval;
   ssize_t pos;
+  process_handle_t process_handle;
   char stdout_buf[100], stderr_buf[100];
 
   /* Start the program */
-  retval = tor_spawn_background(argv[0], &stdout_pipe, &stderr_pipe, argv);
-  tt_int_op(retval, >, 0);
-  tt_int_op(stdout_pipe, >, 0);
-  tt_int_op(stderr_pipe, >, 0);
-  pid = retval;
+  process_handle = tor_spawn_background(argv[0], argv);
+
+  tt_int_op(process_handle.status, ==, 0);
+  tt_int_op(process_handle.stdout_pipe, >, 0);
+  tt_int_op(process_handle.stderr_pipe, >, 0);
 
   /* Check stdout */
-  pos = read_all(stdout_pipe, stdout_buf, sizeof(stdout_buf) - 1, 0);
+  pos = tor_read_all_from_process_stdin(process_handle, stdout_buf,
+		                        sizeof(stdout_buf) - 1);
   tt_assert(pos >= 0);
   stdout_buf[pos] = '\0';
   tt_int_op(pos, ==, strlen(expected_out));
   tt_str_op(stdout_buf, ==, expected_out);
 
   /* Check it terminated correctly */
-  retval = waitpid(pid, &stat_loc, 0);
-  tt_int_op(retval, ==, pid);
-  tt_assert(WIFEXITED(stat_loc));
-  tt_int_op(WEXITSTATUS(stat_loc), ==, expected_exit);
-  tt_assert(!WIFSIGNALED(stat_loc));
-  tt_assert(!WIFSTOPPED(stat_loc));
+  retval = tor_get_exit_code(process_handle);
+  tt_int_op(retval, ==, expected_exit);
 
   /* Check stderr */
-  pos = read_all(stderr_pipe, stderr_buf, sizeof(stderr_buf) - 1, 0);
+  pos = tor_read_all_from_process_stderr(process_handle, stderr_buf,
+		                         sizeof(stderr_buf) - 1);
   tt_assert(pos >= 0);
   stderr_buf[pos] = '\0';
   tt_int_op(pos, ==, strlen(expected_err));
@@ -1447,7 +1443,6 @@ test_util_spawn_background_fail(void *ptr)
 
   run_util_spawn_background(argv, expected_out, expected_err, 255);
 }
-#endif
 
 static void
 test_util_di_ops(void)
@@ -1533,9 +1528,9 @@ struct testcase_t util_tests[] = {
   UTIL_TEST(exit_status, 0),
 #ifndef MS_WINDOWS
   UTIL_TEST(fgets_eagain, TT_SKIP),
+#endif
   UTIL_TEST(spawn_background_ok, 0),
   UTIL_TEST(spawn_background_fail, 0),
-#endif
   END_OF_TESTCASES
 };
 





More information about the tor-commits mailing list