Merge branch 'mgorse'
[platform/core/uifw/at-spi2-atk.git] / dbind / dbind.c
index 4da315b..1bbf0b0 100644 (file)
@@ -98,6 +98,31 @@ dbind_connection_method_call (DBusConnection *cnx,
     return success;
 }
 
+static void set_reply (DBusPendingCall *pending, void *user_data)
+{
+  void **replyptr = (void **)user_data;
+
+  *replyptr = dbus_pending_call_steal_reply (pending);
+}
+
+static DBusMessage *
+send_and_allow_reentry (DBusConnection *bus, DBusMessage *message, int timeout, DBusError *error)
+{
+  DBusPendingCall *pending;
+  DBusMessage *reply = NULL;
+
+  if (!dbus_connection_send_with_reply (bus, message, &pending, timeout))
+  {
+    return NULL;
+  }
+  dbus_pending_call_set_notify (pending, set_reply, (void *)&reply, NULL);
+  while (!reply)
+  {
+    if (!dbus_connection_read_write_dispatch (bus, timeout)) return NULL;
+  }
+  return reply;
+}
+
 dbus_bool_t
 dbind_connection_method_call_va (DBusConnection *cnx,
                                  const char *bus_name,
@@ -112,6 +137,7 @@ dbind_connection_method_call_va (DBusConnection *cnx,
     DBusMessage *msg = NULL, *reply = NULL;
     DBusError *err, real_err;
     char *p;
+    char *dest;
 
     if (opt_error)
         err = opt_error;
@@ -163,11 +189,14 @@ dbind_connection_method_call_va (DBusConnection *cnx,
             case DBUS_TYPE_OBJECT_PATH:
             case DBUS_TYPE_SIGNATURE:
             case DBUS_TYPE_ARRAY:
-            case DBUS_STRUCT_BEGIN_CHAR:
             case DBUS_TYPE_DICT_ENTRY:
                 ptrarg = va_arg (args, void *);
                 arg = &ptrarg;
                 break;
+            case DBUS_STRUCT_BEGIN_CHAR:
+                ptrarg = va_arg (args, void *);
+                arg = ptrarg;
+                break;
 
             case DBUS_TYPE_VARIANT:
                 fprintf (stderr, "No variant support yet - very toolkit specific\n");
@@ -183,10 +212,28 @@ dbind_connection_method_call_va (DBusConnection *cnx,
             }
     }
 
-    reply = dbus_connection_send_with_reply_and_block (cnx, msg, -1, err);
+    dest = dbus_message_get_destination(msg);
+    if (!dest)
+        goto out;
+    if (!strcmp (dbus_bus_get_unique_name(cnx), dest))
+    {
+      /* Can't use dbus_message_send_with_reply_and_block because it will
+       * not pass messages on to the provider side, causing deadlock */
+      reply = send_and_allow_reentry (cnx, msg, -1, err);
+    }
+    else
+    {
+      reply = dbus_connection_send_with_reply_and_block (cnx, msg, -1, err);
+    }
     if (!reply)
         goto out;
 
+    if (dbus_message_get_type (reply) == DBUS_MESSAGE_TYPE_ERROR)
+    {
+      char *name = dbus_message_get_error_name (reply);
+      dbus_set_error (err, name, g_strdup (""));
+      goto out;
+    }
     /* demarshal */
     if (p[0] == '=' && p[1] == '>')
     {