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 <ralf.habacker@freenet.de>
This commit is contained in:
Ralf Habacker 2021-12-20 12:34:14 +01:00
parent 62ccb35996
commit 6bced858cb

View 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;
goto out;
_dbus_string_init (address);
retval = _dbus_string_append (address, shared_addr);
_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;
}