]> git.ipfire.org Git - thirdparty/dbus.git/commitdiff
sysdeps-win: Use the `connection readiness` event when starting dbus-daemon
authorRalf Habacker <ralf.habacker@freenet.de>
Mon, 20 Dec 2021 11:34:14 +0000 (12:34 +0100)
committerRalf Habacker <ralf.habacker@freenet.de>
Mon, 27 Jun 2022 13:32:07 +0000 (15:32 +0200)
In _dbus_get_autolaunch_address() instead of polling at intervals to see
if the shared memory segment is present, the named signal is now used to
reliably get the state of dbus-daemon.

In _dbus_get_autolaunch_shm() the unnecessary initialization of `address`
has been removed, error handling has been improved and the `wait` parameter
has been added to select waiting.

Signed-off-by: Ralf Habacker <ralf.habacker@freenet.de>
dbus/dbus-sysdeps-win.c

index 19e832b4f2effca6dd6cb155f3ffc6f885ece90d..7d4b1bf8a8b647587417ee26e9c984eb3e1fd17d 100644 (file)
@@ -3273,15 +3273,29 @@ _dbus_daemon_unpublish_session_bus_address (void)
   return TRUE;
 }
 
+/**
+ * Get server bus address from shared memory segment provided by running dbus-daemon
+ *
+ * @param address initialized DBusString instance to store the retrieved address
+ * @param shm_name the name of the shared memory segment
+ * @param wait if TRUE wait maximum 2 seconds for the presence of the shared memory segment
+ * @return #TRUE the bus address was fetched from the shared memory segment
+ * @return #FALSE error during execution
+ */
 static dbus_bool_t
-_dbus_get_autolaunch_shm (DBusString *address, DBusString *shm_name)
+_dbus_get_autolaunch_shm (DBusString *address, DBusString *shm_name, dbus_bool_t wait)
 {
-  HANDLE sharedMem;
+  HANDLE sharedMem = NULL;
   char *shared_addr;
   int i;
+  int max = 20; /* max 2 seconds */
+  dbus_bool_t retval = FALSE;
+
+  if (!wait)
+    max = 1;
 
   // read shm
-  for (i = 0; i < 20; ++i)
+  for (i = 0; i < max; ++i)
     {
       // we know that dbus-daemon is available, so we wait until shm is available
       sharedMem = OpenFileMappingA (FILE_MAP_READ, FALSE, _dbus_string_get_const_data (shm_name));
@@ -3297,18 +3311,15 @@ _dbus_get_autolaunch_shm (DBusString *address, DBusString *shm_name)
   shared_addr = MapViewOfFile (sharedMem, FILE_MAP_READ, 0, 0, 0);
 
   if (!shared_addr)
-    return FALSE;
-
-  _dbus_string_init (address);
+    goto out;
 
-  _dbus_string_append (address, shared_addr);
+  retval = _dbus_string_append (address, shared_addr);
 
-  // cleanup
   UnmapViewOfFile (shared_addr);
 
+out:
   CloseHandle (sharedMem);
-
-  return TRUE;
+  return retval;
 }
 
 static dbus_bool_t
@@ -3346,8 +3357,8 @@ _dbus_daemon_already_runs (DBusString *address, DBusString *shm_name, const char
       goto out;
     }
 
-  // read shm
-  retval = _dbus_get_autolaunch_shm (address, shm_name);
+  // read shm, wait max 2 seconds
+  retval = _dbus_get_autolaunch_shm (address, shm_name, TRUE);
 
   // cleanup
   CloseHandle (daemon);
@@ -3374,6 +3385,7 @@ _dbus_get_autolaunch_address (const char *scope,
   DBusString dbus_args = _DBUS_STRING_INIT_INVALID;
   const char *daemon_name = DBUS_DAEMON_NAME ".exe";
   DBusString shm_name;
+  HANDLE ready_event_handle = NULL;
 
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
 
@@ -3461,15 +3473,64 @@ _dbus_get_autolaunch_address (const char *scope,
   if (!_dbus_string_append_printf (&dbus_args, "\"%s\" %s", dbus_exe_path,
                                    autolaunch_custom_command_line_parameter ? autolaunch_custom_command_line_parameter : "--session"))
     {
-      dbus_set_error_const (error, DBUS_ERROR_NO_MEMORY, "Failed to append string to argument buffer");
+      _DBUS_SET_OOM (error);
       retval = FALSE;
       goto out;
     }
 
-  //  argv[i] = "--config-file=bus\\session.conf";
-  if (CreateProcessA (dbus_exe_path, _dbus_string_get_data (&dbus_args), NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
+  ready_event_handle = _dbus_win_event_create_inheritable (error);
+  if (ready_event_handle == NULL)
+    goto out;
+
+  _dbus_verbose ("Creating connection readiness event: handle=%p\n", ready_event_handle);
+  if (!_dbus_string_append_printf (&dbus_args, " \"--ready-event-handle=%p\"", ready_event_handle))
     {
+      _DBUS_SET_OOM (error);
+      goto out;
+    }
+
+  _dbus_verbose ("Starting dbus daemon with args: '%s'\n", _dbus_string_get_const_data (&dbus_args));
+  if (CreateProcessA (dbus_exe_path, _dbus_string_get_data (&dbus_args), NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi))
+    {
+      DWORD status;
+      HANDLE events[2];
+
       CloseHandle (pi.hThread);
+
+      _dbus_verbose ("Wait until dbus-daemon is ready for connections (event handle %p)\n", ready_event_handle);
+
+      events[0] = ready_event_handle;
+      events[1] = pi.hProcess;
+      status = WaitForMultipleObjects (2, events, FALSE, 30000);
+
+      switch (status)
+        {
+        case WAIT_OBJECT_0:
+          /* ready event signalled, everything is okay */
+          retval = TRUE;
+          break;
+
+        case WAIT_OBJECT_0 + 1:
+          /* dbus-daemon process has exited */
+          dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED, "dbus-daemon exited before signalling ready");
+          goto out;
+
+        case WAIT_FAILED:
+          _dbus_win_set_error_from_last_error (error, "Unable to wait for server readiness (handle %p)", ready_event_handle);
+          goto out;
+
+        case WAIT_TIMEOUT:
+          /* GetLastError() is not set */
+          dbus_set_error (error, DBUS_ERROR_TIMEOUT, "Timed out waiting for server readiness or exit (handle %p)", ready_event_handle);
+          goto out;
+
+        default:
+          /* GetLastError() is probably not set? */
+          dbus_set_error (error, DBUS_ERROR_FAILED, "Unknown result '%lu' while waiting for server readiness (handle %p)", status, ready_event_handle);
+          goto out;
+        }
+      _dbus_verbose ("Got signal that dbus-daemon is ready for connections\n");
+
       if (autolaunch_handle_location != NULL)
         {
           *autolaunch_handle_location = pi.hProcess;
@@ -3479,7 +3540,9 @@ _dbus_get_autolaunch_address (const char *scope,
         {
           CloseHandle (pi.hProcess);
         }
-      retval = _dbus_get_autolaunch_shm (address, &shm_name);
+
+      /* do not wait for the appearance of shm, we can assume that it is present */
+      retval = _dbus_get_autolaunch_shm (address, &shm_name, FALSE);
       if (retval == FALSE)
         dbus_set_error_const (error, DBUS_ERROR_FAILED, "Failed to get autolaunch address from launched dbus-daemon");
     }
@@ -3495,7 +3558,10 @@ out:
   _dbus_platform_rmutex_free (lock);
   _dbus_string_free (&shm_name);
   _dbus_string_free (&dbus_args);
+  if (ready_event_handle)
+    _dbus_win_event_free (ready_event_handle, NULL);
 
+  _DBUS_ASSERT_ERROR_XOR_BOOL (error, retval);
   return retval;
 }