From: Ralf Habacker Date: Mon, 20 Dec 2021 11:34:14 +0000 (+0100) Subject: sysdeps-win: Use the `connection readiness` event when starting dbus-daemon X-Git-Tag: dbus-1.15.0~35^2~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=6bced858cbe0a793b2eb116ceefdd47277ebb6c6;p=thirdparty%2Fdbus.git sysdeps-win: Use the `connection readiness` event when starting dbus-daemon 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 --- diff --git a/dbus/dbus-sysdeps-win.c b/dbus/dbus-sysdeps-win.c index 19e832b4f..7d4b1bf8a 100644 --- a/dbus/dbus-sysdeps-win.c +++ b/dbus/dbus-sysdeps-win.c @@ -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; }