GTestDBus: Make work on win32
authorAlexander Larsson <alexl@redhat.com>
Thu, 19 Apr 2012 11:49:52 +0000 (13:49 +0200)
committerAlexander Larsson <alexl@redhat.com>
Thu, 19 Apr 2012 16:19:01 +0000 (18:19 +0200)
Win32 doesn't have things like fork so the existing code has no way
of working. Instead we swap it all out for a custom implementation
on win32.

gio/gtestdbus.c

index dec92fa..b50c383 100644 (file)
 
 #include "glibintl.h"
 
+#ifdef G_OS_WIN32
+#define _WIN32_WINNT 0x0500
+#include <windows.h>
+#endif
+
 /* -------------------------------------------------------------------------- */
 /* Utility: Wait until object has a single ref  */
 
@@ -97,6 +102,44 @@ _g_object_unref_and_wait_weak_notify (gpointer object)
 /* -------------------------------------------------------------------------- */
 /* Utilities to cleanup the mess in the case unit test process crash */
 
+#ifdef G_OS_WIN32
+
+/* This could be interesting to expose in public API */
+static void
+_g_test_watcher_add_pid (GPid pid)
+{
+  static gsize started = 0;
+  HANDLE job;
+
+  if (g_once_init_enter (&started))
+    {
+      JOBOBJECT_EXTENDED_LIMIT_INFORMATION info;
+
+      job = CreateJobObjectW (NULL, NULL);
+      memset (&info, 0, sizeof (info));
+      info.BasicLimitInformation.LimitFlags = 0x2000 /* JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE */;
+
+      if (!SetInformationJobObject(job, JobObjectExtendedLimitInformation, &info, sizeof (info)))
+       g_warning ("Can't enable JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE: %s", g_win32_error_message (GetLastError()));
+
+      g_once_init_leave (&started,(gsize)job);
+    }
+
+  job = (HANDLE)started;
+
+  if (!AssignProcessToJobObject(job, pid))
+    g_warning ("Can't assign process to job: %s", g_win32_error_message (GetLastError()));
+}
+
+static void
+_g_test_watcher_remove_pid (GPid pid)
+{
+  /* No need to unassign the process from the job object as the process
+     will be killed anyway */
+}
+
+#else
+
 #define ADD_PID_FORMAT "add pid %d\n"
 #define REMOVE_PID_FORMAT "remove pid %d\n"
 
@@ -258,6 +301,8 @@ _g_test_watcher_remove_pid (GPid pid)
   g_free (command);
 }
 
+#endif
+
 /* -------------------------------------------------------------------------- */
 /* GTestDBus object implementation */
 
@@ -422,7 +467,12 @@ write_config_file (GTestDBus *self)
   g_string_append (contents,
       "<busconfig>\n"
       "  <type>session</type>\n"
-      "  <listen>unix:tmpdir=/tmp</listen>\n");
+#ifdef G_OS_WIN32
+      "  <listen>nonce-tcp:</listen>\n"
+#else
+      "  <listen>unix:tmpdir=/tmp</listen>\n"
+#endif
+                  );
 
   for (i = 0; i < self->priv->service_dirs->len; i++)
     {
@@ -474,7 +524,11 @@ start_daemon (GTestDBus *self)
   g_spawn_async_with_pipes (NULL,
                             argv,
                             NULL,
-                            G_SPAWN_SEARCH_PATH,
+                            G_SPAWN_SEARCH_PATH
+#ifdef G_OS_WIN32
+                           /* We Need this to get the pid returned on win32 */
+                           | G_SPAWN_DO_NOT_REAP_CHILD,
+#endif
                             NULL,
                             NULL,
                             &self->priv->bus_pid,
@@ -522,8 +576,14 @@ start_daemon (GTestDBus *self)
 static void
 stop_daemon (GTestDBus *self)
 {
+#ifdef G_OS_WIN32
+  if (!TerminateProcess (self->priv->bus_pid, 0))
+    g_warning ("Can't terminate process: %s", g_win32_error_message (GetLastError()));
+#else
   kill (self->priv->bus_pid, SIGTERM);
+#endif
   _g_test_watcher_remove_pid (self->priv->bus_pid);
+  g_spawn_close_pid (self->priv->bus_pid);
   self->priv->bus_pid = 0;
 
   g_free (self->priv->bus_address);