Commit d7f47c99 authored by Tom Gundersen's avatar Tom Gundersen Committed by Mike Gorse
Browse files

bus-launch: add dbus-broker support



Both dbus-daemon and dbus-broker are now optional at compile-time, though
at least one must be configured. A new configuration option is introduce in
order to select the default implementation attempted at runtime. The other
implementation will function as a fall-back (in case support for both are
compiled in). If no default is selected, dbus-daemon remains the default as
before.

Unlike dbus-daemon, dbus-broker requires at-spi-bus-launch to create the
listening socket and pass it in, rather than having the bus do that and send
back the address. For now we follow what dbus-daemon does, and create a socket
in the abstract namespace, though it might be more suitable to create a socket
in $XDG_RUNTIME_DIR.

The only difference users should observe is that daemons are no longer spawned
by the bus implementation, but spawned and managed by the systemd user instance,
though this should not lead to a difference in behavior. In particular this
applies to `org.a11y.atspi.Registry`.

For non-linux and non-systemd systems, dbus-daemon should continue to be used.

[v2:
   - drop the --verbose switch, which is no longer supported
   - make dbus-daemon optional too
   - allow the default implementation to be selected]
Signed-off-by: default avatarTom Gundersen <teg@jklm.no>
parent c210da7e
......@@ -2,7 +2,7 @@
*
* at-spi-bus-launcher: Manage the a11y bus as a child process
*
* Copyright 2011 Red Hat, Inc.
* Copyright 2011-2018 Red Hat, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
......@@ -25,6 +25,11 @@
#include <unistd.h>
#include <string.h>
#include <signal.h>
#ifdef __linux
#include <sys/prctl.h>
#include <sys/socket.h>
#include <sys/un.h>
#endif
#include <sys/wait.h>
#include <errno.h>
#include <stdio.h>
......@@ -58,6 +63,7 @@ typedef struct {
int a11y_bus_pid;
char *a11y_bus_address;
int pipefd[2];
int listenfd;
char *a11y_launch_error_message;
} A11yBusLauncher;
......@@ -215,23 +221,6 @@ name_appeared_handler (GDBusConnection *connection,
register_client (app);
}
static void
setup_bus_child (gpointer data)
{
A11yBusLauncher *app = data;
(void) app;
close (app->pipefd[0]);
dup2 (app->pipefd[1], 3);
close (app->pipefd[1]);
/* On Linux, tell the bus process to exit if this process goes away */
#ifdef __linux
#include <sys/prctl.h>
prctl (PR_SET_PDEATHSIG, 15);
#endif
}
/**
* unix_read_all_fd_to_string:
*
......@@ -276,24 +265,30 @@ on_bus_exited (GPid pid,
g_main_loop_quit (app->loop);
}
#ifdef DBUS_DAEMON
static void
setup_bus_child_daemon (gpointer data)
{
A11yBusLauncher *app = data;
(void) app;
close (app->pipefd[0]);
dup2 (app->pipefd[1], 3);
close (app->pipefd[1]);
/* On Linux, tell the bus process to exit if this process goes away */
#ifdef __linux
prctl (PR_SET_PDEATHSIG, 15);
#endif
}
static gboolean
ensure_a11y_bus (A11yBusLauncher *app)
ensure_a11y_bus_daemon (A11yBusLauncher *app, char *config_path)
{
char *argv[] = { DBUS_DAEMON, config_path, "--nofork", "--print-address", "3", NULL };
GPid pid;
char *argv[] = { DBUS_DAEMON, NULL, "--nofork", "--print-address", "3", NULL };
char addr_buf[2048];
GError *error = NULL;
const char *config_path = NULL;
if (app->a11y_bus_pid != 0)
return FALSE;
if (g_file_test (SYSCONFDIR"/at-spi2/accessibility.conf", G_FILE_TEST_EXISTS))
config_path = "--config-file="SYSCONFDIR"/at-spi2/accessibility.conf";
else
config_path = "--config-file="DATADIR"/defaults/at-spi2/accessibility.conf";
argv[1] = config_path;
if (pipe (app->pipefd) < 0)
g_error ("Failed to create pipe: %s", strerror (errno));
......@@ -302,7 +297,7 @@ ensure_a11y_bus (A11yBusLauncher *app)
argv,
NULL,
G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
setup_bus_child,
setup_bus_child_daemon,
app,
&pid,
&error))
......@@ -335,6 +330,136 @@ ensure_a11y_bus (A11yBusLauncher *app)
app->a11y_bus_address = g_strchomp (g_strdup (addr_buf));
g_debug ("a11y bus address: %s", app->a11y_bus_address);
return TRUE;
error:
close (app->pipefd[0]);
close (app->pipefd[1]);
app->state = A11Y_BUS_STATE_ERROR;
return FALSE;
}
#else
static gboolean
ensure_a11y_bus_daemon (A11yBusLauncher *app, char *config_path)
{
return FALSE;
}
#endif
#ifdef DBUS_BROKER
static void
setup_bus_child_broker (gpointer data)
{
A11yBusLauncher *app = data;
gchar *pid_str;
(void) app;
dup2 (app->listenfd, 3);
close (app->listenfd);
g_setenv("LISTEN_FDS", "1", TRUE);
pid_str = g_strdup_printf("%u", getpid());
g_setenv("LISTEN_PID", pid_str, TRUE);
g_free(pid_str);
/* Tell the bus process to exit if this process goes away */
prctl (PR_SET_PDEATHSIG, SIGTERM);
}
static gboolean
ensure_a11y_bus_broker (A11yBusLauncher *app, char *config_path)
{
char *argv[] = { DBUS_BROKER, config_path, "--scope", "user", NULL };
struct sockaddr_un addr = { .sun_family = AF_UNIX };
socklen_t addr_len = sizeof(addr);
GPid pid;
GError *error = NULL;
if ((app->listenfd = socket (PF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0)) < 0)
g_error ("Failed to create listening socket: %s", strerror (errno));
if (bind (app->listenfd, (struct sockaddr *)&addr, sizeof(sa_family_t)) < 0)
g_error ("Failed to bind listening socket: %s", strerror (errno));
if (getsockname (app->listenfd, (struct sockaddr *)&addr, &addr_len) < 0)
g_error ("Failed to get socket name for listening socket: %s", strerror(errno));
if (listen (app->listenfd, 1024) < 0)
g_error ("Failed to listen on socket: %s", strerror(errno));
if (!g_spawn_async (NULL,
argv,
NULL,
G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
setup_bus_child_broker,
app,
&pid,
&error))
{
app->a11y_bus_pid = -1;
app->a11y_launch_error_message = g_strdup (error->message);
g_clear_error (&error);
goto error;
}
close (app->listenfd);
app->listenfd = -1;
g_child_watch_add (pid, on_bus_exited, app);
app->a11y_bus_pid = pid;
g_debug ("Launched a11y bus, child is %ld", (long) pid);
app->state = A11Y_BUS_STATE_RUNNING;
app->a11y_bus_address = g_strconcat("unix:abstract=", addr.sun_path + 1, NULL);
g_debug ("a11y bus address: %s", app->a11y_bus_address);
return TRUE;
error:
close (app->listenfd);
app->state = A11Y_BUS_STATE_ERROR;
return FALSE;
}
#else
static gboolean
ensure_a11y_bus_broker (A11yBusLauncher *app, char *config_path)
{
return FALSE;
}
#endif
static gboolean
ensure_a11y_bus (A11yBusLauncher *app)
{
char *config_path = NULL;
gboolean success = FALSE;
if (app->a11y_bus_pid != 0)
return FALSE;
if (g_file_test (SYSCONFDIR"/at-spi2/accessibility.conf", G_FILE_TEST_EXISTS))
config_path = "--config-file="SYSCONFDIR"/at-spi2/accessibility.conf";
else
config_path = "--config-file="DATADIR"/defaults/at-spi2/accessibility.conf";
#ifdef WANT_DBUS_BROKER
success = ensure_a11y_bus_broker (app, config_path);
if (!success)
{
if (!ensure_a11y_bus_daemon (app, config_path))
return FALSE;
}
#else
success = ensure_a11y_bus_daemon (app, config_path);
if (!success)
{
if (!ensure_a11y_bus_broker (app, config_path))
return FALSE;
}
#endif
#ifdef HAVE_X11
{
Display *display = XOpenDisplay (NULL);
......@@ -353,13 +478,6 @@ ensure_a11y_bus (A11yBusLauncher *app)
#endif
return TRUE;
error:
close (app->pipefd[0]);
close (app->pipefd[1]);
app->state = A11Y_BUS_STATE_ERROR;
return FALSE;
}
static void
......
......@@ -31,8 +31,13 @@ configure_file(input: 'at-spi-dbus-bus.service.in',
install: true,
install_dir: systemd_user_dir)
launcher_args = [
'-DSYSCONFDIR="@0@"'.format(atspi_sysconfdir),
'-DDATADIR="@0@"'.format(atspi_datadir),
]
if get_option('dbus_daemon') != 'default'
dbus_daemon = get_option('dbus_daemon')
launcher_args += '-DDBUS_DAEMON="@0@"'.format(get_option('dbus_daemon'))
else
dbus_daemon = find_program('dbus-daemon',
'/sbin/dbus-daemon',
......@@ -40,16 +45,29 @@ else
'/libexec/dbus-daemon',
'/usr/libexec/dbus-daemon',
'/usr/pkg/bin/dbus-daemon',
required: true).path()
required: false)
if dbus_daemon.found()
launcher_args += '-DDBUS_DAEMON="@0@"'.format(dbus_daemon.path())
endif
endif
if get_option('dbus_broker') != 'default'
launcher_args += '-DDBUS_BROKER="@0@"'.format(get_option('dbus_broker'))
else
dbus_broker = find_program('dbus-broker-launch',
required: false)
if dbus_broker.found()
launcher_args += '-DDBUS_BROKER="@0@"'.format(dbus_broker.path())
endif
endif
if get_option('default_bus') == 'dbus-broker'
launcher_args += '-DWANT_DBUS_BROKER'
endif
executable('at-spi-bus-launcher', 'at-spi-bus-launcher.c',
include_directories: [ root_inc, include_directories('.') ],
dependencies: [ gio_dep, x11_deps ],
c_args: [
'-DSYSCONFDIR="@0@"'.format(atspi_sysconfdir),
'-DDATADIR="@0@"'.format(atspi_datadir),
'-DDBUS_DAEMON="@0@"'.format(dbus_daemon),
],
c_args: launcher_args,
install: true,
install_dir: atspi_libexecdir)
......@@ -6,6 +6,15 @@ option('dbus_daemon',
description: 'The path of the DBus daemon',
type: 'string',
value: 'default')
option('dbus_broker',
description: 'The path of the DBus broker',
type: 'string',
value: 'default')
option('default_bus',
description: 'The default DBus implementation to use',
type: 'combo',
choices: ['dbus-daemon', 'dbus-broker'],
value: 'dbus-daemon')
option('systemd_user_dir',
description: 'Location of the systemd user services',
type: 'string',
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment