aboutsummaryrefslogtreecommitdiff
path: root/src/lib/process/process.c
diff options
context:
space:
mode:
authorAlexander Færøy <ahf@torproject.org>2018-11-22 04:49:23 +0100
committerNick Mathewson <nickm@torproject.org>2018-12-17 16:39:28 -0500
commitbb784cf4f36256a8276ba60641d3ff766b9cd9df (patch)
tree347af5c98bbeb2edcd4655f6740de9358b70ab62 /src/lib/process/process.c
parent2e957027e28449d4c3254cc404d154f4bce41bfc (diff)
downloadtor-bb784cf4f36256a8276ba60641d3ff766b9cd9df.tar.gz
tor-bb784cf4f36256a8276ba60641d3ff766b9cd9df.zip
Add Windows backend for the Process subsystem.
This patch adds support for Microsoft Windows in the Process subsystem. Libevent does not support mixing different types of handles (sockets, named pipes, etc.) on Windows in its core event loop code. This have historically meant that Tor have avoided attaching any non-networking handles to the event loop. This patch uses a slightly different approach to roughly support the same features for the Process subsystem as we do with the Unix backend. In this patch we use Windows Extended I/O functions (ReadFileEx() and WriteFileEx()) which executes asynchronously in the background and executes a completion routine when the scheduled read or write operation have completed. This is much different from the Unix backend where the operating system signals to us whenever a file descriptor is "ready" to either being read from or written to. To make the Windows operating system execute the completion routines of ReadFileEx() and WriteFileEx() we must get the Tor process into what Microsoft calls an "alertable" state. To do this we execute SleepEx() with a zero millisecond sleep time from a main loop timer that ticks once a second. This moves the process into the "alertable" state and when we return from the zero millisecond timeout all the outstanding I/O completion routines will be called and we can schedule the next reads and writes. The timer loop is also responsible for detecting whether our child processes have terminated since the last timer tick. See: https://bugs.torproject.org/28179
Diffstat (limited to 'src/lib/process/process.c')
-rw-r--r--src/lib/process/process.c35
1 files changed, 33 insertions, 2 deletions
diff --git a/src/lib/process/process.c b/src/lib/process/process.c
index 8d6a9d3fa0..d4237b2b1f 100644
--- a/src/lib/process/process.c
+++ b/src/lib/process/process.c
@@ -16,6 +16,7 @@
#include "lib/log/util_bug.h"
#include "lib/process/process.h"
#include "lib/process/process_unix.h"
+#include "lib/process/process_win32.h"
#include "lib/process/env.h"
#ifdef HAVE_STDDEF_H
@@ -69,6 +70,9 @@ struct process_t {
#ifndef _WIN32
/** Our Unix process handle. */
process_unix_t *unix_process;
+#else
+ /** Our Win32 process handle. */
+ process_win32_t *win32_process;
#endif
};
@@ -117,6 +121,10 @@ void
process_init(void)
{
processes = smartlist_new();
+
+#ifdef _WIN32
+ process_win32_init();
+#endif
}
/** Free up all resources that is handled by the Process subsystem. Note that
@@ -124,6 +132,10 @@ process_init(void)
void
process_free_all(void)
{
+#ifdef _WIN32
+ process_win32_deinit();
+#endif
+
SMARTLIST_FOREACH(processes, process_t *, x, process_free(x));
smartlist_free(processes);
}
@@ -170,6 +182,9 @@ process_new(const char *command)
#ifndef _WIN32
/* Prepare our Unix process handle. */
process->unix_process = process_unix_new();
+#else
+ /* Prepare our Win32 process handle. */
+ process->win32_process = process_win32_new();
#endif
smartlist_add(processes, process);
@@ -202,6 +217,9 @@ process_free_(process_t *process)
#ifndef _WIN32
/* Cleanup our Unix process handle. */
process_unix_free(process->unix_process);
+#else
+ /* Cleanup our Win32 process handle. */
+ process_win32_free(process->win32_process);
#endif
smartlist_remove(processes, process);
@@ -222,6 +240,8 @@ process_exec(process_t *process)
#ifndef _WIN32
status = process_unix_exec(process);
+#else
+ status = process_win32_exec(process);
#endif
/* Update our state. */
@@ -420,6 +440,15 @@ process_get_unix_process(const process_t *process)
tor_assert(process->unix_process);
return process->unix_process;
}
+#else
+/** Get the internal handle for Windows backend. */
+process_win32_t *
+process_get_win32_process(const process_t *process)
+{
+ tor_assert(process);
+ tor_assert(process->win32_process);
+ return process->win32_process;
+}
#endif
/** Write <b>size</b> bytes of <b>data</b> to the given process's standard
@@ -544,7 +573,7 @@ MOCK_IMPL(STATIC int, process_read_stdout, (process_t *process, buf_t *buffer))
#ifndef _WIN32
return process_unix_read_stdout(process, buffer);
#else
- return 0;
+ return process_win32_read_stdout(process, buffer);
#endif
}
@@ -559,7 +588,7 @@ MOCK_IMPL(STATIC int, process_read_stderr, (process_t *process, buf_t *buffer))
#ifndef _WIN32
return process_unix_read_stderr(process, buffer);
#else
- return 0;
+ return process_win32_read_stderr(process, buffer);
#endif
}
@@ -573,6 +602,8 @@ MOCK_IMPL(STATIC void, process_write_stdin,
#ifndef _WIN32
process_unix_write(process, buffer);
+#else
+ process_win32_write(process, buffer);
#endif
}