[tor-commits] [tor/master] Make a version of tor_read_all_handle() for non-Windows platforms

nickm at torproject.org nickm at torproject.org
Thu Sep 1 02:12:47 UTC 2011


commit 5b8a20ed447f11cda2e0bf528dd78e41e4b76fa4
Author: Steven Murdoch <Steven.Murdoch at cl.cam.ac.uk>
Date:   Thu Sep 1 01:06:12 2011 +0100

    Make a version of tor_read_all_handle() for non-Windows platforms
    
    Mainly used for testing reading from subprocesses. To be more generic
    we now pass in a pointer to a process_handle_t rather than a Windows-
    specific HANDLE.
---
 src/common/util.c    |   72 +++++++++++++++++++++++++++++++++++++++++--------
 src/common/util.h    |   13 +++++---
 src/test/test_util.c |   43 ++++++++++++++++++------------
 3 files changed, 94 insertions(+), 34 deletions(-)

diff --git a/src/common/util.c b/src/common/util.c
index 09eb969..30c298e 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -3522,7 +3522,8 @@ tor_get_exit_code(const process_handle_t process_handle,
  * only once the process has exited, or <b>count</b> bytes are read. Returns
  * the number of bytes read, or -1 on error. */
 ssize_t
-tor_read_all_handle(HANDLE h, char *buf, size_t count, HANDLE hProcess)
+tor_read_all_handle(HANDLE h, char *buf, size_t count,
+                    const process_handle_t *process)
 {
   size_t numread = 0;
   BOOL retval;
@@ -3544,7 +3545,7 @@ tor_read_all_handle(HANDLE h, char *buf, size_t count, HANDLE hProcess)
       /* Nothing available: process exited or it is busy */
 
       /* Exit if we don't know whether the process is running */
-      if (NULL == hProcess)
+      if (NULL == process)
         break;
 
       /* The process exited and there's nothing left to read from it */
@@ -3554,7 +3555,8 @@ tor_read_all_handle(HANDLE h, char *buf, size_t count, HANDLE hProcess)
       /* If process is not running, check for output one more time in case
          it wrote something after the peek was performed. Otherwise keep on
          waiting for output */
-      byte_count = WaitForSingleObject(hProcess, 0);
+      tor_assert(process != NULL);
+      byte_count = WaitForSingleObject(process->pid.hProcess, 0);
       if (WAIT_TIMEOUT != byte_count)
         process_exited = TRUE;
 
@@ -3576,31 +3578,77 @@ tor_read_all_handle(HANDLE h, char *buf, size_t count, HANDLE hProcess)
   }
   return (ssize_t)numread;
 }
+#else
+/** Read from a handle <b>h</b> into <b>buf</b>, up to <b>count</b> bytes.  If
+ * <b>process</b> is NULL, the function will return immediately if there is
+ * nothing more to read. Otherwise data will be read until end of file, or
+ * <b>count</b> bytes are read.  Returns the number of bytes read, or -1 on
+ * error. */
+ssize_t
+tor_read_all_handle(FILE *h, char *buf, size_t count,
+                    const process_handle_t *process)
+{
+  size_t numread = 0;
+  char *retval;
+
+  if (count > SIZE_T_CEILING || count > SSIZE_T_MAX)
+    return -1;
+
+  while (numread != count) {
+    /* Use fgets because that is what we use in log_from_pipe() */
+    retval = fgets(buf+numread, (int)(count-numread), h);
+    if (NULL == retval) {
+      if (feof(h)) {
+        fclose(h);
+        break;
+      } else {
+        if (EAGAIN == errno) {
+          if (process)
+            continue;
+          else
+            break;
+        } else {
+          log_warn(LD_GENERAL, "fgets() from handle failed: %s",
+                   strerror(errno));
+          fclose(h);
+          return -1;
+        }
+      }
+    }
+    tor_assert(retval != NULL);
+    numread += strlen(retval);
+  }
+
+  log_debug(LD_GENERAL, "fgets read %d bytes from handle", (int)numread);
+  return (ssize_t)numread;
+}
 #endif
 
 /** Read from stdout of a process until the process exits. */
 ssize_t
-tor_read_all_from_process_stdout(const process_handle_t process_handle,
-                                char *buf, size_t count)
+tor_read_all_from_process_stdout(const process_handle_t *process_handle,
+                                 char *buf, size_t count)
 {
 #ifdef MS_WINDOWS
-  return tor_read_all_handle(process_handle.stdout_pipe, buf, count,
-                             process_handle.pid.hProcess);
+  return tor_read_all_handle(process_handle->stdout_pipe, buf, count,
+                             process_handle);
 #else
-  return read_all(process_handle.stdout_pipe, buf, count, 0);
+  return tor_read_all_handle(process_handle->stdout_handle, buf, count,
+                             process_handle);
 #endif
 }
 
 /** Read from stdout of a process until the process exits. */
 ssize_t
-tor_read_all_from_process_stderr(const process_handle_t process_handle,
+tor_read_all_from_process_stderr(const process_handle_t *process_handle,
                                  char *buf, size_t count)
 {
 #ifdef MS_WINDOWS
-  return tor_read_all_handle(process_handle.stderr_pipe, buf, count,
-                             process_handle.pid.hProcess);
+  return tor_read_all_handle(process_handle->stderr_pipe, buf, count,
+                             process_handle);
 #else
-  return read_all(process_handle.stderr_pipe, buf, count, 0);
+  return tor_read_all_handle(process_handle->stderr_handle, buf, count,
+                             process_handle);
 #endif
 }
 
diff --git a/src/common/util.h b/src/common/util.h
index 3029425..6211267 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -388,12 +388,15 @@ int tor_get_exit_code(const process_handle_t process_handle,
 int tor_split_lines(struct smartlist_t *sl, char *buf, int len);
 #ifdef MS_WINDOWS
 ssize_t tor_read_all_handle(HANDLE h, char *buf, size_t count,
-                            HANDLE hProcess);
+                            const process_handle_t *process);
+#else
+ssize_t tor_read_all_handle(FILE *h, char *buf, size_t count,
+                            const process_handle_t *process);
 #endif
-ssize_t tor_read_all_from_process_stdout(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);
+ssize_t tor_read_all_from_process_stdout(
+    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);
 char *tor_join_win_cmdline(const char *argv[]);
 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 b903cbf..336f95b 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -1404,8 +1404,8 @@ run_util_spawn_background(const char *argv[], const char *expected_out,
   tt_int_op(process_handle.stderr_pipe, >, 0);
 
   /* Check stdout */
-  pos = tor_read_all_from_process_stdout(process_handle, stdout_buf,
-                                        sizeof(stdout_buf) - 1);
+  pos = tor_read_all_from_process_stdout(&process_handle, stdout_buf,
+                                         sizeof(stdout_buf) - 1);
   tt_assert(pos >= 0);
   stdout_buf[pos] = '\0';
   tt_str_op(stdout_buf, ==, expected_out);
@@ -1418,7 +1418,7 @@ run_util_spawn_background(const char *argv[], const char *expected_out,
   // TODO: Make test-child exit with something other than 0
 
   /* Check stderr */
-  pos = tor_read_all_from_process_stderr(process_handle, stderr_buf,
+  pos = tor_read_all_from_process_stderr(&process_handle, stderr_buf,
                                          sizeof(stderr_buf) - 1);
   tt_assert(pos >= 0);
   stderr_buf[pos] = '\0';
@@ -1493,57 +1493,66 @@ test_util_spawn_background_partial_read(void *ptr)
                                  "DONE\r\n",
                                  NULL };
   const char *expected_err = "ERR\r\n";
-  int expected_out_ctr;
 #else
   const char *argv[] = {BUILDDIR "/src/test/test-child", "--test", NULL};
-  const char *expected_out = "OUT\n--test\nSLEEPING\nDONE\n";
-  const char *expected_err = "ERR\r\n";
+  const char *expected_out[] = { "OUT\n--test\nSLEEPING\n",
+                                 "DONE\n",
+                                 NULL };
+  const char *expected_err = "ERR\n";
 #endif
+  int expected_out_ctr;
   (void)ptr;
 
   /* Start the program */
+#ifdef MS_WINDOWS
   tor_spawn_background(NULL, argv, &process_handle);
+#else
+  tor_spawn_background(argv[0], argv, &process_handle);
+#endif
   tt_int_op(process_handle.status, ==, expected_status);
 
   /* Check stdout */
-#ifdef MS_WINDOWS
   for (expected_out_ctr =0; expected_out[expected_out_ctr] != NULL;) {
+#ifdef MS_WINDOWS
     pos = tor_read_all_handle(process_handle.stdout_pipe, stdout_buf,
                               sizeof(stdout_buf) - 1, NULL);
+#else
+    pos = tor_read_all_handle(process_handle.stdout_handle, stdout_buf,
+                              sizeof(stdout_buf) - 1, NULL);
+#endif
     log_info(LD_GENERAL, "tor_read_all_handle() returned %d", (int)pos);
 
     /* We would have blocked, keep on trying */
     if (0 == pos)
       continue;
 
-    tt_assert(pos >= 0);
+    tt_int_op(pos, >=, 0);
     stdout_buf[pos] = '\0';
     tt_str_op(stdout_buf, ==, expected_out[expected_out_ctr]);
     tt_int_op(pos, ==, strlen(expected_out[expected_out_ctr]));
     expected_out_ctr++;
   }
+
   /* The process should have exited without writing more */
+#ifdef MS_WINDOWS
   pos = tor_read_all_handle(process_handle.stdout_pipe, stdout_buf,
                             sizeof(stdout_buf) - 1,
-                            process_handle.pid.hProcess);
-  tt_int_op(pos, ==, 0);
+                            &process_handle);
 #else
-  pos = tor_read_all_from_process_stdout(process_handle, stdout_buf,
-                                         sizeof(stdout_buf) - 1);
-  tt_assert(pos >= 0);
-  stdout_buf[pos] = '\0';
-  tt_str_op(stdout_buf, ==, expected_out);
-  tt_int_op(pos, ==, strlen(expected_out));
+  pos = tor_read_all_handle(process_handle.stdout_handle, stdout_buf,
+                            sizeof(stdout_buf) - 1,
+                            &process_handle);
 #endif
 
   /* Check it terminated correctly */
   retval = tor_get_exit_code(process_handle, 1, &exit_code);
   tt_int_op(retval, ==, PROCESS_EXIT_EXITED);
   tt_int_op(exit_code, ==, expected_exit);
+
   // TODO: Make test-child exit with something other than 0
 
   /* Check stderr */
-  pos = tor_read_all_from_process_stderr(process_handle, stderr_buf,
+  pos = tor_read_all_from_process_stderr(&process_handle, stderr_buf,
                                          sizeof(stderr_buf) - 1);
   tt_assert(pos >= 0);
   stderr_buf[pos] = '\0';





More information about the tor-commits mailing list