[PATCH] config: if we can't connect to HAL, listen for a startup notification.

Peter Hutterer peter.hutterer at who-t.net
Wed Feb 4 21:45:51 PST 2009


If HAL isn't available when we try to connect, register a NameOwnerChanged
handler and wait until HAL is available. This allows HAL to be started in
parallel or after the server has started.

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
 config/hal.c |   98 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 94 insertions(+), 4 deletions(-)

diff --git a/config/hal.c b/config/hal.c
index 8dfbb07..c662562 100644
--- a/config/hal.c
+++ b/config/hal.c
@@ -467,11 +467,10 @@ disconnect_hook(void *data)
     info->system_bus = NULL;
 }
 
-static void
-connect_hook(DBusConnection *connection, void *data)
+static BOOL
+connect_and_register(DBusConnection *connection, struct config_hal_info *info)
 {
     DBusError error;
-    struct config_hal_info *info = data;
     char **devices;
     int num_devices, i;
 
@@ -512,7 +511,7 @@ connect_hook(DBusConnection *connection, void *data)
 
     dbus_error_free(&error);
 
-    return;
+    return TRUE;
 
 out_ctx2:
     if (!libhal_ctx_shutdown(info->hal_ctx, &error))
@@ -526,6 +525,97 @@ out_err:
     info->hal_ctx = NULL;
     info->system_bus = NULL;
 
+    return FALSE;
+}
+
+
+/**
+ * Handle NewOwnerChanged signals to deal with HAL startup at X server runtime.
+ *
+ * NewOwnerChanged is send once when HAL shuts down, and once again when it
+ * comes back up. Message has three arguments, first is the name
+ * (org.freedesktop.Hal), the second one is the old owner, third one is new
+ * owner.
+ */
+static DBusHandlerResult
+ownerchanged_handler(DBusConnection *connection, DBusMessage *message, void *data)
+{
+    int ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+    if (dbus_message_is_signal(message,
+                               "org.freedesktop.DBus",
+                               "NameOwnerChanged")) {
+        DBusError error;
+        char *name, *old_owner, *new_owner;
+
+        dbus_error_init(&error);
+        dbus_message_get_args(message, &error,
+                              DBUS_TYPE_STRING, &name,
+                              DBUS_TYPE_STRING, &old_owner,
+                              DBUS_TYPE_STRING, &new_owner,
+                              DBUS_TYPE_INVALID);
+
+        if (dbus_error_is_set(&error)) {
+            ErrorF("[config/hal] failed to get NameOwnerChanged args: %s (%s)\n",
+                   error.name, error.message);
+        } else if (name && strcmp(name, "org.freedesktop.Hal") == 0) {
+
+            if (!old_owner || !strlen(old_owner)) {
+                DebugF("[config/hal] HAL startup detected.\n");
+                if (connect_and_register(connection, (struct config_hal_info*)data))
+                    dbus_connection_unregister_object_path(connection,
+                                                     "/org/freedesktop/DBus");
+                else
+                    ErrorF("[config/hal] Failed to connect to HAL bus.\n");
+            }
+
+            ret = DBUS_HANDLER_RESULT_HANDLED;
+        }
+        dbus_error_free(&error);
+    }
+
+    return ret;
+}
+
+/**
+ * Register a handler for the NameOwnerChanged signal.
+ */
+static void
+listen_for_startup(DBusConnection *connection, void *data)
+{
+    DBusObjectPathVTable vtable = { .message_function = ownerchanged_handler, };
+    DBusError error;
+    const char MATCH_RULE[] = "sender='org.freedesktop.DBus',"
+                              "interface='org.freedesktop.DBus',"
+                              "type='signal',"
+                              "path='/org/freedesktop/DBus',"
+                              "member='NameOwnerChanged'";
+
+    dbus_error_init(&error);
+    dbus_bus_add_match(connection, MATCH_RULE, &error);
+    if (!dbus_error_is_set(&error)) {
+        if (!dbus_connection_register_object_path(connection,
+                                                  "/org/freedesktop/DBus",
+                                                  &vtable,
+                                                  data))
+            ErrorF("[config/hal] cannot register object path.\n");
+    } else {
+        ErrorF("[config/hal] couldn't add match rule: %s (%s)\n", error.name,
+                error.message);
+        ErrorF("[config/hal] cannot detect a HAL startup.\n");
+    }
+
+    dbus_error_free(&error);
+}
+
+static void
+connect_hook(DBusConnection *connection, void *data)
+{
+    struct config_hal_info *info = data;
+
+    if (!connect_and_register(connection, info))
+        listen_for_startup(connection, data);
+
     return;
 }
 
-- 
1.6.0.6




More information about the xorg mailing list