kdbus: make access error behaviour consistent with dbus-daemon 41/172741/1
authorAleksy Barcz <a.barcz@partner.samsung.com>
Thu, 15 Mar 2018 11:43:28 +0000 (12:43 +0100)
committerAleksy Barcz <a.barcz@partner.samsung.com>
Thu, 15 Mar 2018 12:32:39 +0000 (13:32 +0100)
Bugfix. When used with dbus-daemon, when an AccessDenied or ServiceUnknown
error occurs, gdbus returns a dbus error message to the sender (synchronously
or asynchronously) and doesn't set GError. Up to now the kdbus implementation
didn't return any error message and did set GError, which made the following
low-level functions behaviour inconsistent between dbus-daemon and kdbus:

g_dbus_connection_send_message_with_reply_sync
g_dbus_connection_send_message_with_reply
g_dbus_connection_send_message_with_reply_finish

This patch makes this behaviour consistent. Any code that relied on the inconsistent
behaviour should be corrected. The high-level function interface, returning GVariants
is NOT affected by this change.

Change-Id: I60cd4822ccef0e0fc0d7b99244f4ceb03512b97f

gio/gkdbus.c

index a09aef0..b3885d2 100755 (executable)
@@ -3533,6 +3533,55 @@ compute_msg_size (GDBusMessage    *message,
   return sizeof (struct kdbus_msg) + items_size;
 }
 
+typedef struct
+{
+  GKDBusWorker  *worker;
+  GDBusMessage  *message;
+} SyntheticReplyData;
+
+static gboolean
+deliver_synthetic_reply (gpointer user_data)
+{
+  SyntheticReplyData *data;
+  GKDBusWorker *worker;
+  GDBusMessage *message;
+
+  data = user_data;
+  worker = data->worker;
+  message = data->message;
+
+  (* worker->message_received_callback) (message, worker->user_data);
+
+  g_object_unref (message);
+  g_free (data);
+
+  return FALSE;
+}
+
+static GDBusMessage*
+create_access_error_reply (GDBusMessage *message,
+                           GError *error)
+{
+  GDBusMessage *error_reply;
+  gchar *dbus_error_name;
+  dbus_error_name = g_dbus_error_encode_gerror (error);
+  error_reply = g_dbus_message_new_method_error (message, dbus_error_name, "%s", error->message);
+  g_free (dbus_error_name);
+  return error_reply;
+}
+
+static void
+send_error_message (GKDBusWorker *worker,
+                    GDBusMessage *message)
+{
+  SyntheticReplyData *reply_data;
+  reply_data = g_new0 (SyntheticReplyData, 1);
+  reply_data->worker = worker;
+  reply_data->message = message;
+  g_main_context_invoke (worker->context, deliver_synthetic_reply, reply_data);
+}
+
+
 /*
  * _g_kdbus_send
  */
@@ -3557,6 +3606,8 @@ _g_kdbus_send (GKDBusWorker  *worker,
   gsize header_size;
   gsize msg_size;
 
+  GDBusMessage *access_error_message;
+
   g_return_val_if_fail (G_IS_KDBUS_WORKER (worker), FALSE);
 
   send = NULL;
@@ -3735,6 +3786,19 @@ _g_kdbus_send (GKDBusWorker  *worker,
                   break;
                 }
 
+
+              access_error_message = create_access_error_reply(message, *error);
+              g_clear_error(error); /* we send back an error reply, so error must be NULL */
+              result = TRUE;
+              if (out_reply != NULL)
+                {
+                  *out_reply = access_error_message;
+                }
+              else
+                {
+                  send_error_message(worker, access_error_message);
+                }
+
               goto out;
             }
         }
@@ -4011,31 +4075,6 @@ g_kdbus_ready (gint           fd,
   return G_SOURCE_CONTINUE;
 }
 
-typedef struct
-{
-  GKDBusWorker  *worker;
-  GDBusMessage  *message;
-} SyntheticReplyData;
-
-static gboolean
-deliver_synthetic_reply (gpointer user_data)
-{
-  SyntheticReplyData *data;
-  GKDBusWorker *worker;
-  GDBusMessage *message;
-
-  data = user_data;
-  worker = data->worker;
-  message = data->message;
-
-  (* worker->message_received_callback) (message, worker->user_data);
-
-  g_object_unref (message);
-  g_free (data);
-
-  return FALSE;
-}
-
 void
 _g_kdbus_worker_unfreeze (GKDBusWorker *worker)
 {