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