LogoopenSUSE Build Service > Projects
Sign Up | Log In

View File dbus-fall-back-to-old-run-directory.patch of Package dbus-1 (Project home:dsterba:project211)

diff --git a/dbus/dbus-bus.c b/dbus/dbus-bus.c
index fadc3a8..2c71cdb 100644
--- a/dbus/dbus-bus.c
+++ b/dbus/dbus-bus.c
@@ -421,6 +421,153 @@ _dbus_bus_notify_shared_connection_disconnected_unlocked (DBusConnection *connec
   _DBUS_UNLOCK (bus);
 }
 
+static dbus_bool_t
+internal_register (DBusConnection *connection,
+                   int             timeout_milliseconds,
+                   DBusError      *error)
+{
+  DBusMessage *message, *reply;
+  char *name;
+  BusData *bd;
+  dbus_bool_t retval;
+
+  _dbus_return_val_if_fail (connection != NULL, FALSE);
+  _dbus_return_val_if_error_is_set (error, FALSE);
+
+  retval = FALSE;
+  message = NULL;
+  reply = NULL;
+
+  _DBUS_LOCK (bus_datas);
+
+  bd = ensure_bus_data (connection);
+  if (bd == NULL)
+    {
+      _DBUS_SET_OOM (error);
+      goto out;
+    }
+
+  if (bd->unique_name != NULL)
+    {
+      _dbus_verbose ("Ignoring attempt to register the same DBusConnection %s with the message bus a second time.\n",
+                     bd->unique_name);
+      /* Success! */
+      retval = TRUE;
+      goto out;
+    }
+  
+  message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+                                          DBUS_PATH_DBUS,
+                                          DBUS_INTERFACE_DBUS,
+                                          "Hello"); 
+
+  if (!message)
+    {
+      _DBUS_SET_OOM (error);
+      goto out;
+    }
+  
+  reply = dbus_connection_send_with_reply_and_block (connection, message, timeout_milliseconds, error);
+
+  if (reply == NULL)
+    goto out;
+  else if (dbus_set_error_from_message (error, reply))
+    goto out;
+  else if (!dbus_message_get_args (reply, error,
+                                   DBUS_TYPE_STRING, &name,
+                                   DBUS_TYPE_INVALID))
+    goto out;
+  
+  bd->unique_name = _dbus_strdup (name);
+  if (bd->unique_name == NULL)
+    {
+      _DBUS_SET_OOM (error);
+      goto out;
+    }
+  
+  retval = TRUE;
+  
+ out:
+  _DBUS_UNLOCK (bus_datas);
+
+  if (message)
+    dbus_message_unref (message);
+
+  if (reply)
+    dbus_message_unref (reply);
+
+  return retval;
+}
+
+static DBusConnection *
+internal_open_and_register (const char *address, dbus_bool_t private, int timeout_milliseconds, DBusError *error)
+{
+  DBusConnection *connection;
+
+  if (private)
+    connection = dbus_connection_open_private (address, error);
+  else
+    connection = dbus_connection_open (address, error);
+
+  if (!connection)
+    {
+      goto out;
+    }
+
+  if (!internal_register (connection, timeout_milliseconds, error))
+    {
+      _dbus_connection_close_possibly_shared (connection);
+      dbus_connection_unref (connection);
+      connection = NULL;
+      goto out;
+    }
+
+out:
+  return connection;
+}
+
+/* When the D-Bus upgrade that moves /var/run/dbus/ to /run/dbus/ is applied,
+ * D-Bus cannot be restarted with the new socket in /run/, because the session
+ * wouldn't be able to cope with it. We end up with a daemon listening on
+ * /var/run/dbus/system_bus_socket, but clients will now try to register
+ * with it on /run/dbus/system_bus_socket, causing the upgrade, and eventually
+ * critical parts of the user's session, to hang.
+ *
+ * The workaround is inelegant, but probably good enough: We allow the initial
+ * attempt to time out quickly and fall back to trying the old default address.
+ * If that fails too, we go back to blocking on the initial address. */
+
+#define OLD_SYSTEM_BUS_DEFAULT_ADDRESS "unix:path=/var/run/dbus/system_bus_socket"
+#define INITIAL_TIMEOUT_MILLISECONDS 250
+#define INCREMENT_TIMEOUT_MILLISECONDS 250
+#define MAX_TIMEOUT_MILLISECONDS 10000
+
+static DBusConnection *
+internal_open_and_register_with_fallback (const char *address, dbus_bool_t private, DBusError *error)
+{
+  DBusConnection *connection = NULL;
+  int timeout_milliseconds;
+
+  for (timeout_milliseconds = INITIAL_TIMEOUT_MILLISECONDS;
+       connection == NULL && timeout_milliseconds < MAX_TIMEOUT_MILLISECONDS;
+       timeout_milliseconds += INCREMENT_TIMEOUT_MILLISECONDS)
+    {
+      connection = internal_open_and_register (address, private, timeout_milliseconds, NULL);
+
+      if (!connection && !strcmp (address, DBUS_SYSTEM_BUS_DEFAULT_ADDRESS))
+          connection = internal_open_and_register (OLD_SYSTEM_BUS_DEFAULT_ADDRESS, private, timeout_milliseconds, NULL);
+    }
+
+  if (!connection)
+    {
+      /* We couldn't register with any of the sockets; fall back to original behavior, blocking
+       * forever or returning an error. */
+      connection = internal_open_and_register (address, private, -1, error);
+    }
+
+  return connection;
+}
+
 static DBusConnection *
 internal_bus_get (DBusBusType  type,
                   dbus_bool_t  private,
@@ -474,21 +621,10 @@ internal_bus_get (DBusBusType  type,
       goto out;
     }
 
-  if (private)
-    connection = dbus_connection_open_private (address, error);
-  else
-    connection = dbus_connection_open (address, error);
-  
-  if (!connection)
-    {
-      goto out;
-    }
+  connection = internal_open_and_register_with_fallback (address, private, error);
 
-  if (!dbus_bus_register (connection, error))
+  if (!connection)
     {
-      _dbus_connection_close_possibly_shared (connection);
-      dbus_connection_unref (connection);
-      connection = NULL;
       goto out;
     }
 
diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c
index ee33b6c..b87c6f7 100644
--- a/dbus/dbus-connection.c
+++ b/dbus/dbus-connection.c
@@ -348,7 +348,7 @@ static void               _dbus_connection_update_dispatch_status_and_unlock (DB
 static void               _dbus_connection_last_unref                        (DBusConnection     *connection);
 static void               _dbus_connection_acquire_dispatch                  (DBusConnection     *connection);
 static void               _dbus_connection_release_dispatch                  (DBusConnection     *connection);
-static DBusDispatchStatus _dbus_connection_flush_unlocked                    (DBusConnection     *connection);
+static DBusDispatchStatus _dbus_connection_flush_unlocked                    (DBusConnection     *connection, int timeout_milliseconds);
 static void               _dbus_connection_close_possibly_shared_and_unlock  (DBusConnection     *connection);
 static dbus_bool_t        _dbus_connection_get_is_connected_unlocked         (DBusConnection     *connection);
 static dbus_bool_t        _dbus_connection_peek_for_reply_unlocked           (DBusConnection     *connection,
@@ -2367,7 +2367,7 @@ _dbus_connection_block_pending_call (DBusPendingCall *pending)
   DBusConnection *connection;
   dbus_uint32_t client_serial;
   DBusTimeout *timeout;
-  int timeout_milliseconds, elapsed_milliseconds;
+  int timeout_milliseconds = -1, elapsed_milliseconds;
 
   _dbus_assert (pending != NULL);
 
@@ -2379,7 +2379,12 @@ _dbus_connection_block_pending_call (DBusPendingCall *pending)
   connection = _dbus_pending_call_get_connection_and_lock (pending);
   
   /* Flush message queue - note, can affect dispatch status */
-  _dbus_connection_flush_unlocked (connection);
+
+  timeout = _dbus_pending_call_get_timeout_unlocked (pending);
+  if (timeout)
+    timeout_milliseconds = dbus_timeout_get_interval (timeout);
+
+  _dbus_connection_flush_unlocked (connection, timeout_milliseconds);
 
   client_serial = _dbus_pending_call_get_reply_serial_unlocked (pending);
 
@@ -3555,7 +3560,7 @@ dbus_connection_send_with_reply_and_block (DBusConnection     *connection,
  * @param connection the connection.
  */
 static DBusDispatchStatus
-_dbus_connection_flush_unlocked (DBusConnection *connection)
+_dbus_connection_flush_unlocked (DBusConnection *connection, int timeout_milliseconds)
 {
   /* We have to specify DBUS_ITERATION_DO_READING here because
    * otherwise we could have two apps deadlock if they are both doing
@@ -3563,20 +3568,36 @@ _dbus_connection_flush_unlocked (DBusConnection *connection)
    * dispatch status.
    */
   DBusDispatchStatus status;
+  long start_tv_sec, start_tv_usec;
+  long tv_sec, tv_usec;
+  int elapsed_milliseconds = 0;
 
   HAVE_LOCK_CHECK (connection);
+
+  _dbus_get_monotonic_time (&start_tv_sec, &start_tv_usec);
   
   while (connection->n_outgoing > 0 &&
          _dbus_connection_get_is_connected_unlocked (connection))
     {
       _dbus_verbose ("doing iteration in\n");
+
+      if (timeout_milliseconds >= 0)
+        {
+          _dbus_get_monotonic_time (&tv_sec, &tv_usec);
+          elapsed_milliseconds = (tv_sec - start_tv_sec) * 1000 +
+            (tv_usec - start_tv_usec) / 1000;
+
+          if (elapsed_milliseconds >= timeout_milliseconds)
+            break;
+        }
+
       HAVE_LOCK_CHECK (connection);
       _dbus_connection_do_iteration_unlocked (connection,
                                               NULL,
                                               DBUS_ITERATION_DO_READING |
                                               DBUS_ITERATION_DO_WRITING |
                                               DBUS_ITERATION_BLOCK,
-                                              -1);
+                                              timeout_milliseconds - elapsed_milliseconds);
     }
 
   HAVE_LOCK_CHECK (connection);
@@ -3606,7 +3627,7 @@ dbus_connection_flush (DBusConnection *connection)
   
   CONNECTION_LOCK (connection);
 
-  status = _dbus_connection_flush_unlocked (connection);
+  status = _dbus_connection_flush_unlocked (connection, -1);
   
   HAVE_LOCK_CHECK (connection);
   /* Unlocks and calls out to user code */