David Herrmann 3af577
From 09e012860a6e1e074ac1950a4afc3d4131d046d9 Mon Sep 17 00:00:00 2001
David Herrmann 3af577
From: Tom Gundersen <teg@jklm.no>
David Herrmann 3af577
Date: Thu, 1 Mar 2018 12:00:09 +0100
David Herrmann 3af577
Subject: [PATCH] bus-launch: add dbus-broker support
David Herrmann 3af577
David Herrmann 3af577
If dbus-broker is enabled at compile-time and found at run-time prefer that
David Herrmann 3af577
over dbus-daemon.
David Herrmann 3af577
David Herrmann 3af577
Unlike with dbus-daemon, this means that at-spi-bus-launch must create the
David Herrmann 3af577
listening socket and pass it in, rather than having the bus do that and send
David Herrmann 3af577
back the address. For now we follow what dbus-daemon does, and create a socket
David Herrmann 3af577
in the abstract namespace, though it might be more suitable to create a socket
David Herrmann 3af577
in $XDG_RUNTIME_DIR.
David Herrmann 3af577
David Herrmann 3af577
The only difference users should observe is that daemons are no longer spawned
David Herrmann 3af577
by the bus implementation, but spawned and managed by the systemd user instance,
David Herrmann 3af577
though this should not lead to a difference in behavior. In particular this
David Herrmann 3af577
applies to `org.a11y.atspi.Registry`.
David Herrmann 3af577
David Herrmann 3af577
For non-linux and non-systemd systems, dbus-daemon should continue to be used.
David Herrmann 3af577
David Herrmann 3af577
Signed-off-by: Tom Gundersen <teg@jklm.no>
David Herrmann 3af577
---
David Herrmann 3af577
 bus/at-spi-bus-launcher.c | 145 ++++++++++++++++++++++++++++++++++++++--------
David Herrmann 3af577
 bus/meson.build           |  27 +++++++--
David Herrmann 3af577
 meson_options.txt         |   4 ++
David Herrmann 3af577
 3 files changed, 147 insertions(+), 29 deletions(-)
David Herrmann 3af577
David Herrmann 3af577
diff --git a/bus/at-spi-bus-launcher.c b/bus/at-spi-bus-launcher.c
David Herrmann 3af577
index eb2b8e3..8aeb490 100644
David Herrmann 3af577
--- a/bus/at-spi-bus-launcher.c
David Herrmann 3af577
+++ b/bus/at-spi-bus-launcher.c
David Herrmann 3af577
@@ -2,7 +2,7 @@
David Herrmann 3af577
  * 
David Herrmann 3af577
  * at-spi-bus-launcher: Manage the a11y bus as a child process 
David Herrmann 3af577
  *
David Herrmann 3af577
- * Copyright 2011 Red Hat, Inc.
David Herrmann 3af577
+ * Copyright 2011-2018 Red Hat, Inc.
David Herrmann 3af577
  *
David Herrmann 3af577
  * This library is free software; you can redistribute it and/or
David Herrmann 3af577
  * modify it under the terms of the GNU Library General Public
David Herrmann 3af577
@@ -25,6 +25,11 @@
David Herrmann 3af577
 #include <unistd.h>
David Herrmann 3af577
 #include <string.h>
David Herrmann 3af577
 #include <signal.h>
David Herrmann 3af577
+#ifdef __linux
David Herrmann 3af577
+#include <sys/prctl.h>
David Herrmann 3af577
+#include <sys/socket.h>
David Herrmann 3af577
+#include <sys/un.h>
David Herrmann 3af577
+#endif
David Herrmann 3af577
 #include <sys/wait.h>
David Herrmann 3af577
 #include <errno.h>
David Herrmann 3af577
 #include <stdio.h>
David Herrmann 3af577
@@ -58,6 +63,7 @@ typedef struct {
David Herrmann 3af577
   int a11y_bus_pid;
David Herrmann 3af577
   char *a11y_bus_address;
David Herrmann 3af577
   int pipefd[2];
David Herrmann 3af577
+  int listenfd;
David Herrmann 3af577
   char *a11y_launch_error_message;
David Herrmann 3af577
 } A11yBusLauncher;
David Herrmann 3af577
 
David Herrmann 3af577
@@ -216,7 +222,7 @@ name_appeared_handler (GDBusConnection *connection,
David Herrmann 3af577
 }
David Herrmann 3af577
 
David Herrmann 3af577
 static void
David Herrmann 3af577
-setup_bus_child (gpointer data)
David Herrmann 3af577
+setup_bus_child_daemon (gpointer data)
David Herrmann 3af577
 {
David Herrmann 3af577
   A11yBusLauncher *app = data;
David Herrmann 3af577
   (void) app;
David Herrmann 3af577
@@ -227,7 +233,6 @@ setup_bus_child (gpointer data)
David Herrmann 3af577
 
David Herrmann 3af577
   /* On Linux, tell the bus process to exit if this process goes away */
David Herrmann 3af577
 #ifdef __linux
David Herrmann 3af577
-#include <sys/prctl.h>
David Herrmann 3af577
   prctl (PR_SET_PDEATHSIG, 15);
David Herrmann 3af577
 #endif  
David Herrmann 3af577
 }
David Herrmann 3af577
@@ -277,23 +282,12 @@ on_bus_exited (GPid     pid,
David Herrmann 3af577
 } 
David Herrmann 3af577
 
David Herrmann 3af577
 static gboolean
David Herrmann 3af577
-ensure_a11y_bus (A11yBusLauncher *app)
David Herrmann 3af577
+ensure_a11y_bus_daemon (A11yBusLauncher *app, char *config_path)
David Herrmann 3af577
 {
David Herrmann 3af577
+  char *argv[] = { DBUS_DAEMON, config_path, "--nofork", "--print-address", "3", NULL };
David Herrmann 3af577
   GPid pid;
David Herrmann 3af577
-  char *argv[] = { DBUS_DAEMON, NULL, "--nofork", "--print-address", "3", NULL };
David Herrmann 3af577
   char addr_buf[2048];
David Herrmann 3af577
   GError *error = NULL;
David Herrmann 3af577
-  const char *config_path = NULL;
David Herrmann 3af577
-
David Herrmann 3af577
-  if (app->a11y_bus_pid != 0)
David Herrmann 3af577
-    return FALSE;
David Herrmann 3af577
-
David Herrmann 3af577
-  if (g_file_test (SYSCONFDIR"/at-spi2/accessibility.conf", G_FILE_TEST_EXISTS))
David Herrmann 3af577
-      config_path = "--config-file="SYSCONFDIR"/at-spi2/accessibility.conf";
David Herrmann 3af577
-  else
David Herrmann 3af577
-      config_path = "--config-file="DATADIR"/defaults/at-spi2/accessibility.conf";
David Herrmann 3af577
-
David Herrmann 3af577
-  argv[1] = config_path;
David Herrmann 3af577
 
David Herrmann 3af577
   if (pipe (app->pipefd) < 0)
David Herrmann 3af577
     g_error ("Failed to create pipe: %s", strerror (errno));
David Herrmann 3af577
@@ -302,7 +296,7 @@ ensure_a11y_bus (A11yBusLauncher *app)
David Herrmann 3af577
                       argv,
David Herrmann 3af577
                       NULL,
David Herrmann 3af577
                       G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
David Herrmann 3af577
-                      setup_bus_child,
David Herrmann 3af577
+                      setup_bus_child_daemon,
David Herrmann 3af577
                       app,
David Herrmann 3af577
                       &pid,
David Herrmann 3af577
                       &error))
David Herrmann 3af577
@@ -335,6 +329,116 @@ ensure_a11y_bus (A11yBusLauncher *app)
David Herrmann 3af577
   app->a11y_bus_address = g_strchomp (g_strdup (addr_buf));
David Herrmann 3af577
   g_debug ("a11y bus address: %s", app->a11y_bus_address);
David Herrmann 3af577
 
David Herrmann 3af577
+  return TRUE;
David Herrmann 3af577
+
David Herrmann 3af577
+error:
David Herrmann 3af577
+  close (app->pipefd[0]);
David Herrmann 3af577
+  close (app->pipefd[1]);
David Herrmann 3af577
+  app->state = A11Y_BUS_STATE_ERROR;
David Herrmann 3af577
+
David Herrmann 3af577
+  return FALSE;
David Herrmann 3af577
+}
David Herrmann 3af577
+
David Herrmann 3af577
+#ifdef DBUS_BROKER
David Herrmann 3af577
+static void
David Herrmann 3af577
+setup_bus_child_broker (gpointer data)
David Herrmann 3af577
+{
David Herrmann 3af577
+  A11yBusLauncher *app = data;
David Herrmann 3af577
+  gchar *pid_str;
David Herrmann 3af577
+  (void) app;
David Herrmann 3af577
+
David Herrmann 3af577
+  dup2 (app->listenfd, 3);
David Herrmann 3af577
+  close (app->listenfd);
David Herrmann 3af577
+  g_setenv("LISTEN_FDS", "1", TRUE);
David Herrmann 3af577
+
David Herrmann 3af577
+  pid_str = g_strdup_printf("%u", getpid());
David Herrmann 3af577
+  g_setenv("LISTEN_PID", pid_str, TRUE);
David Herrmann 3af577
+  g_free(pid_str);
David Herrmann 3af577
+
David Herrmann 3af577
+  /* Tell the bus process to exit if this process goes away */
David Herrmann 3af577
+  prctl (PR_SET_PDEATHSIG, SIGTERM);
David Herrmann 3af577
+}
David Herrmann 3af577
+
David Herrmann 3af577
+static gboolean
David Herrmann 3af577
+ensure_a11y_bus_broker (A11yBusLauncher *app, char *config_path)
David Herrmann 3af577
+{
David Herrmann 3af577
+  char *argv[] = { DBUS_BROKER, config_path, "--scope", "user", "--verbose", NULL };
David Herrmann 3af577
+  struct sockaddr_un addr = { .sun_family = AF_UNIX };
David Herrmann 3af577
+  socklen_t addr_len = sizeof(addr);
David Herrmann 3af577
+  GPid pid;
David Herrmann 3af577
+  GError *error = NULL;
David Herrmann 3af577
+
David Herrmann 3af577
+  if ((app->listenfd = socket (PF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0)) < 0)
David Herrmann 3af577
+    g_error ("Failed to create listening socket: %s", strerror (errno));
David Herrmann 3af577
+
David Herrmann 3af577
+  if (bind (app->listenfd, (struct sockaddr *)&addr, sizeof(sa_family_t)) < 0)
David Herrmann 3af577
+    g_error ("Failed to bind listening socket: %s", strerror (errno));
David Herrmann 3af577
+
David Herrmann 3af577
+  if (getsockname (app->listenfd, (struct sockaddr *)&addr, &addr_len) < 0)
David Herrmann 3af577
+    g_error ("Failed to get socket name for listening socket: %s", strerror(errno));
David Herrmann 3af577
+
David Herrmann 3af577
+  if (listen (app->listenfd, 1024) < 0)
David Herrmann 3af577
+    g_error ("Failed to listen on socket: %s", strerror(errno));
David Herrmann 3af577
+
David Herrmann 3af577
+  if (!g_spawn_async (NULL,
David Herrmann 3af577
+                      argv,
David Herrmann 3af577
+                      NULL,
David Herrmann 3af577
+                      G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
David Herrmann 3af577
+                      setup_bus_child_broker,
David Herrmann 3af577
+                      app,
David Herrmann 3af577
+                      &pid,
David Herrmann 3af577
+                      &error))
David Herrmann 3af577
+    {
David Herrmann 3af577
+      app->a11y_bus_pid = -1;
David Herrmann 3af577
+      app->a11y_launch_error_message = g_strdup (error->message);
David Herrmann 3af577
+      g_clear_error (&error);
David Herrmann 3af577
+      goto error;
David Herrmann 3af577
+    }
David Herrmann 3af577
+
David Herrmann 3af577
+  close (app->listenfd);
David Herrmann 3af577
+  app->listenfd = -1;
David Herrmann 3af577
+
David Herrmann 3af577
+  g_child_watch_add (pid, on_bus_exited, app);
David Herrmann 3af577
+  app->a11y_bus_pid = pid;
David Herrmann 3af577
+  g_debug ("Launched a11y bus, child is %ld", (long) pid);
David Herrmann 3af577
+  app->state = A11Y_BUS_STATE_RUNNING;
David Herrmann 3af577
+
David Herrmann 3af577
+  app->a11y_bus_address = g_strconcat("unix:abstract=", addr.sun_path + 1, NULL);
David Herrmann 3af577
+  g_debug ("a11y bus address: %s", app->a11y_bus_address);
David Herrmann 3af577
+
David Herrmann 3af577
+  return TRUE;
David Herrmann 3af577
+
David Herrmann 3af577
+error:
David Herrmann 3af577
+  close (app->listenfd);
David Herrmann 3af577
+  app->state = A11Y_BUS_STATE_ERROR;
David Herrmann 3af577
+
David Herrmann 3af577
+  return FALSE;
David Herrmann 3af577
+}
David Herrmann 3af577
+#endif
David Herrmann 3af577
+
David Herrmann 3af577
+static gboolean
David Herrmann 3af577
+ensure_a11y_bus (A11yBusLauncher *app)
David Herrmann 3af577
+{
David Herrmann 3af577
+  char *config_path = NULL;
David Herrmann 3af577
+  gboolean success = FALSE;
David Herrmann 3af577
+
David Herrmann 3af577
+  if (app->a11y_bus_pid != 0)
David Herrmann 3af577
+    return FALSE;
David Herrmann 3af577
+
David Herrmann 3af577
+  if (g_file_test (SYSCONFDIR"/at-spi2/accessibility.conf", G_FILE_TEST_EXISTS))
David Herrmann 3af577
+      config_path = "--config-file="SYSCONFDIR"/at-spi2/accessibility.conf";
David Herrmann 3af577
+  else
David Herrmann 3af577
+      config_path = "--config-file="DATADIR"/defaults/at-spi2/accessibility.conf";
David Herrmann 3af577
+
David Herrmann 3af577
+#ifdef DBUS_BROKER
David Herrmann 3af577
+    success = ensure_a11y_bus_broker (app, config_path);
David Herrmann 3af577
+#endif
David Herrmann 3af577
+  if (!success)
David Herrmann 3af577
+    {
David Herrmann 3af577
+      if (!ensure_a11y_bus_daemon (app, config_path))
David Herrmann 3af577
+          return FALSE;
David Herrmann 3af577
+    }
David Herrmann 3af577
+
David Herrmann 3af577
 #ifdef HAVE_X11
David Herrmann 3af577
   {
David Herrmann 3af577
     Display *display = XOpenDisplay (NULL);
David Herrmann 3af577
@@ -353,13 +457,6 @@ ensure_a11y_bus (A11yBusLauncher *app)
David Herrmann 3af577
 #endif
David Herrmann 3af577
 
David Herrmann 3af577
   return TRUE;
David Herrmann 3af577
-  
David Herrmann 3af577
- error:
David Herrmann 3af577
-  close (app->pipefd[0]);
David Herrmann 3af577
-  close (app->pipefd[1]);
David Herrmann 3af577
-  app->state = A11Y_BUS_STATE_ERROR;
David Herrmann 3af577
-
David Herrmann 3af577
-  return FALSE;
David Herrmann 3af577
 }
David Herrmann 3af577
 
David Herrmann 3af577
 static void
David Herrmann 3af577
diff --git a/bus/meson.build b/bus/meson.build
David Herrmann 3af577
index 909103c..ba8ea2c 100644
David Herrmann 3af577
--- a/bus/meson.build
David Herrmann 3af577
+++ b/bus/meson.build
David Herrmann 3af577
@@ -43,13 +43,30 @@ else
David Herrmann 3af577
                              required: true).path()
David Herrmann 3af577
 endif
David Herrmann 3af577
 
David Herrmann 3af577
-executable('at-spi-bus-launcher', 'at-spi-bus-launcher.c',
David Herrmann 3af577
-           include_directories: [ root_inc, include_directories('.') ],
David Herrmann 3af577
-           dependencies: [ gio_dep, x11_deps ],
David Herrmann 3af577
-           c_args: [
David Herrmann 3af577
+launcher_args = [
David Herrmann 3af577
              '-DSYSCONFDIR="@0@"'.format(atspi_sysconfdir),
David Herrmann 3af577
              '-DDATADIR="@0@"'.format(atspi_datadir),
David Herrmann 3af577
              '-DDBUS_DAEMON="@0@"'.format(dbus_daemon),
David Herrmann 3af577
-           ],
David Herrmann 3af577
+           ]
David Herrmann 3af577
+
David Herrmann 3af577
+if get_option('dbus_broker') != 'default'
David Herrmann 3af577
+  launcher_args += '-DDBUS_BROKER="@0@"'.format(get_option('dbus_broker'))
David Herrmann 3af577
+else
David Herrmann 3af577
+  dbus_broker = find_program('dbus-broker-launch',
David Herrmann 3af577
+                             '/sbin/dbus-broker-launch',
David Herrmann 3af577
+                             '/usr/sbin/dbus-broker-launch',
David Herrmann 3af577
+                             '/libexec/dbus-broker-launch',
David Herrmann 3af577
+                             '/usr/libexec/dbus-broker-launch',
David Herrmann 3af577
+                             '/usr/pkg/bin/dbus-broker-launch',
David Herrmann 3af577
+                             required: false)
David Herrmann 3af577
+  if dbus_broker.found()
David Herrmann 3af577
+    launcher_args += '-DDBUS_BROKER="@0@"'.format(dbus_broker.path())
David Herrmann 3af577
+  endif
David Herrmann 3af577
+endif
David Herrmann 3af577
+
David Herrmann 3af577
+executable('at-spi-bus-launcher', 'at-spi-bus-launcher.c',
David Herrmann 3af577
+           include_directories: [ root_inc, include_directories('.') ],
David Herrmann 3af577
+           dependencies: [ gio_dep, x11_deps ],
David Herrmann 3af577
+           c_args: launcher_args,
David Herrmann 3af577
            install: true,
David Herrmann 3af577
            install_dir: atspi_libexecdir)
David Herrmann 3af577
diff --git a/meson_options.txt b/meson_options.txt
David Herrmann 3af577
index c9afe2f..494e83a 100644
David Herrmann 3af577
--- a/meson_options.txt
David Herrmann 3af577
+++ b/meson_options.txt
David Herrmann 3af577
@@ -6,6 +6,10 @@ option('dbus_daemon',
David Herrmann 3af577
        description: 'The path of the DBus daemon',
David Herrmann 3af577
        type: 'string',
David Herrmann 3af577
        value: 'default')
David Herrmann 3af577
+option('dbus_broker',
David Herrmann 3af577
+       description: 'The path of the DBus broker',
David Herrmann 3af577
+       type: 'string',
David Herrmann 3af577
+       value: 'default')
David Herrmann 3af577
 option('systemd_user_dir',
David Herrmann 3af577
        description: 'Location of the systemd user services',
David Herrmann 3af577
        type: 'string',