kdbus: modified to support asynchronous StartServiceByName 99/200099/5
authorsanghyeok.oh <sanghyeok.oh@samsung.com>
Tue, 19 Feb 2019 06:47:41 +0000 (15:47 +0900)
committerAdrian Szyndela <adrian.s@samsung.com>
Thu, 27 Jun 2019 14:06:02 +0000 (16:06 +0200)
Change-Id: I57c30fb86b1ec266037a4583ef64888ca92f2bc9
Signed-off-by: sanghyeok.oh <sanghyeok.oh@samsung.com>
gio/gdbusconnection.c
gio/gkdbus.c
gio/gkdbus.h
gio/gkdbusfakedaemon.c
gio/gkdbusfakedaemon.h

index 56ea38e..0c2844c 100755 (executable)
@@ -1462,7 +1462,7 @@ schedule_closed_unlocked (GDBusConnection *connection,
  * of the thread that @connection was constructed in.
  *
  * This is an asynchronous method. When the operation is finished,
- * @callback will be invoked in the 
+ * @callback will be invoked in the
  * [thread-default main context][g-main-context-push-thread-default]
  * of the thread you are calling this method from. You can
  * then call g_dbus_connection_close_finish() to get the result of the
@@ -2200,7 +2200,7 @@ g_dbus_start_service_by_name (GDBusConnection  *connection,
 
 #ifdef G_OS_UNIX
   if (connection->kdbus_worker)
-    return _g_kdbus_StartServiceByName (connection->kdbus_worker, name, flags, error);
+    return _g_kdbus_StartServiceByName (connection->kdbus_worker, name, flags, NULL, error);
 #endif
 
   result = g_dbus_connection_call_sync (connection, "org.freedesktop.DBus", "/",
@@ -2665,7 +2665,7 @@ g_dbus_connection_send_message_with_reply_unlocked (GDBusConnection     *connect
  * the operation fails with %G_IO_ERROR_INVALID_ARGUMENT.
  *
  * This is an asynchronous method. When the operation is finished, @callback
- * will be invoked in the 
+ * will be invoked in the
  * [thread-default main context][g-main-context-push-thread-default]
  * of the thread you are calling this method from. You can then call
  * g_dbus_connection_send_message_with_reply_finish() to get the result of the operation.
@@ -4235,7 +4235,7 @@ is_signal_data_for_name_lost_or_acquired (SignalData *signal_data)
  *     subscription is removed or %NULL
  *
  * Subscribes to signals on @connection and invokes @callback with a whenever
- * the signal is received. Note that @callback will be invoked in the 
+ * the signal is received. Note that @callback will be invoked in the
  * [thread-default main context][g-main-context-push-thread-default]
  * of the thread you are calling this method from.
  *
@@ -6026,7 +6026,7 @@ obj_message_func (GDBusConnection *connection,
  * D-Bus interface that is described in @interface_info.
  *
  * Calls to functions in @vtable (and @user_data_free_func) will happen
- * in the 
+ * in the
  * [thread-default main context][g-main-context-push-thread-default]
  * of the thread you are calling this method from.
  *
index 2b06396..cbc366a 100755 (executable)
@@ -1631,6 +1631,92 @@ _g_kdbus_GetConnectionSecurityLabel (GKDBusWorker  *worker,
   return sec_label;
 }
 
+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 gboolean
+_g_kdbus_StartServiceByName_helper (gpointer user_data)
+{
+  SyntheticReplyData *data;
+  GKDBusWorker *worker;
+  GDBusMessage *message;
+  const gchar *name;
+  GDBusMessage *ping_message;
+  GDBusMessage *reply;
+  GError *local_error;
+  gboolean ret;
+  GVariant *body;
+
+  data = (SyntheticReplyData *)user_data;
+  worker = data->worker;
+  message = data->message;
+
+  name = NULL;
+  reply = NULL;
+  local_error = NULL;
+
+  body = g_dbus_message_get_body (message);
+  g_variant_get(body, "(su)", &name, NULL);
+
+  ping_message = g_dbus_message_new_method_call (name, "/", "org.freedesktop.DBus.Peer", "Ping");
+
+  g_dbus_message_set_serial (ping_message, -1);
+
+  /* check synchronous */
+  ret = _g_kdbus_send (worker, ping_message, &reply, 25000, NULL, NULL);
+  if (!ret)
+    {
+      gchar *dbus_error_name;
+
+      g_set_error (&local_error,
+                    G_DBUS_ERROR,
+                    G_DBUS_ERROR_SERVICE_UNKNOWN,
+                    "The name %s was not provided by any .service files", g_dbus_message_get_destination(message));
+
+      dbus_error_name = g_dbus_error_encode_gerror (local_error);
+      reply = g_dbus_message_new_method_error (message, dbus_error_name, "%s", local_error->message);
+
+      g_free (dbus_error_name);
+      g_error_free (local_error);
+    }
+  else
+    {
+      reply = g_dbus_message_new_method_reply (message);
+      g_dbus_message_set_body (reply, g_variant_new ("(u)", G_BUS_START_SERVICE_REPLY_SUCCESS));
+    }
+
+  g_dbus_message_set_serial (reply, -1);
+  data->message = reply;
+  g_main_context_invoke (worker->context, deliver_synthetic_reply, data);
+
+  g_free (name);
+  g_object_unref (ping_message);
+  g_object_unref (message);
+
+  return FALSE;
+}
 
 /* < internal >
  *
@@ -1646,6 +1732,7 @@ GBusStartServiceReplyFlags
 _g_kdbus_StartServiceByName (GKDBusWorker  *worker,
                              const gchar   *name,
                              guint32        flags,
+                             GDBusMessage  *message,
                              GError       **error)
 {
   GBusStartServiceReplyFlags status;
@@ -1664,30 +1751,46 @@ _g_kdbus_StartServiceByName (GKDBusWorker  *worker,
 
   if (!g_kdbus_NameHasOwner_internal (worker, name))
     {
-      GDBusMessage *message;
+      gboolean ret;
       GDBusMessage *reply;
-      gint ret;
+      gboolean sync;
 
       reply = NULL;
+      status = G_BUS_START_SERVICE_REPLY_SUCCESS;
+      sync = message ? FALSE : TRUE;
 
-      message = g_dbus_message_new_method_call (name, "/", "org.freedesktop.DBus.Peer", "Ping");
-      g_dbus_message_set_serial (message, -1);
-
-      ret = _g_kdbus_send (worker, message, &reply, 25000, NULL, NULL);
-      if (!ret)
+      if (sync)
         {
-          g_set_error (error,
-                       G_DBUS_ERROR,
-                       G_DBUS_ERROR_SERVICE_UNKNOWN,
-                       "The name %s was not provided by any .service files", name);
-          status = G_BUS_START_SERVICE_REPLY_ERROR;
+          GDBusMessage *ping_message;
+
+          ping_message = g_dbus_message_new_method_call (name, "/", "org.freedesktop.DBus.Peer", "Ping");
+          g_dbus_message_set_serial (ping_message, -1);
+
+          ret = _g_kdbus_send (worker, ping_message, &reply, 25000, NULL, NULL);
+          g_object_unref (reply);
+
+          if (!ret)
+            {
+              status = G_BUS_START_SERVICE_REPLY_ERROR;
+
+              g_set_error (error,
+                          G_DBUS_ERROR,
+                          G_DBUS_ERROR_SERVICE_UNKNOWN,
+                          "The name %s was not provided by any .service files", name);
+            }
+          g_object_unref (ping_message);
         }
       else
         {
-         g_object_unref (reply);
-         status = G_BUS_START_SERVICE_REPLY_SUCCESS;
+          SyntheticReplyData *data;
+
+          data = g_new0 (SyntheticReplyData, 1);
+
+          data->worker = worker;
+          data->message = g_object_ref (message);
+
+          g_main_context_invoke (worker->context, _g_kdbus_StartServiceByName_helper, data);
         }
-      g_object_unref (message);
     }
   else
     status = G_BUS_START_SERVICE_REPLY_ALREADY_RUNNING;
@@ -3572,31 +3675,6 @@ 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;
-}
-
 #ifdef LIBDBUSPOLICY
 static GDBusMessage*
 create_access_error_reply (GDBusMessage *message,
@@ -4160,14 +4238,20 @@ _g_kdbus_worker_send_message (GKDBusWorker  *worker,
 #ifdef DBUS_DAEMON_EMULATION
   if (_is_message_to_dbus_daemon (message))
     {
-      SyntheticReplyData *data;
+      GDBusMessage *reply = NULL;
+      reply = _dbus_daemon_synthetic_reply (worker, message, FALSE);
 
-      data = g_new0 (SyntheticReplyData, 1);
+      if (reply)
+        {
+          SyntheticReplyData *data;
+
+          data = g_new0 (SyntheticReplyData, 1);
 
-      data->worker = worker;
-      data->message = _dbus_daemon_synthetic_reply (worker, message);
+          data->worker = worker;
+          data->message = reply;
 
-      g_main_context_invoke (worker->context, deliver_synthetic_reply, data);
+          g_main_context_invoke (worker->context, deliver_synthetic_reply, data);
+        }
 
       return TRUE;
     }
@@ -4187,7 +4271,7 @@ _g_kdbus_worker_send_message_sync (GKDBusWorker  *worker,
 #ifdef DBUS_DAEMON_EMULATION
   if (_is_message_to_dbus_daemon (message))
     {
-      *out_reply = _dbus_daemon_synthetic_reply (worker, message);
+      *out_reply = _dbus_daemon_synthetic_reply (worker, message, TRUE);
       return TRUE;
     }
 #endif /* DBUS_DAEMON_EMULATION */
index a245f92..acbc0d5 100644 (file)
@@ -163,6 +163,7 @@ gchar *                     _g_kdbus_GetConnectionSecurityLabel      (GKDBusWork
 GBusStartServiceReplyFlags  _g_kdbus_StartServiceByName              (GKDBusWorker     *worker,
                                                                       const gchar      *name,
                                                                       guint32           flags,
+                                                                      GDBusMessage     *message,
                                                                       GError          **error);
 
 gboolean                    _g_kdbus_AddMatch                        (GKDBusWorker     *worker,
index c13bf49..04272f3 100644 (file)
@@ -146,7 +146,8 @@ _is_message_to_dbus_daemon (GDBusMessage  *message)
  */
 GDBusMessage *
 _dbus_daemon_synthetic_reply (GKDBusWorker  *worker,
-                              GDBusMessage  *message)
+                              GDBusMessage  *message,
+                              gboolean sync)
 {
   GDBusMessage *reply;
   GVariant     *reply_body;
@@ -621,9 +622,18 @@ _dbus_daemon_synthetic_reply (GKDBusWorker  *worker,
 
           g_variant_get (body, "(&su)", &name, &flags);
 
-          status = _g_kdbus_StartServiceByName (worker, name, flags, &local_error);
+          if (sync)
+            status = _g_kdbus_StartServiceByName (worker, name, flags, NULL, &local_error);
+          else
+            status = _g_kdbus_StartServiceByName (worker, name, flags, message, &local_error);
+
           if (local_error == NULL)
-            reply_body = g_variant_new ("(u)", status);
+            {
+              if (status == G_BUS_START_SERVICE_REPLY_ALREADY_RUNNING || sync)
+                reply_body = g_variant_new ("(u)", status);
+              else
+                return NULL;
+            }
         }
       else
         g_set_error (&local_error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
index 7378671..969b7b5 100644 (file)
@@ -32,7 +32,8 @@
 gboolean              _is_message_to_dbus_daemon             (GDBusMessage  *message);
 
 GDBusMessage *        _dbus_daemon_synthetic_reply           (GKDBusWorker  *worker,
-                                                              GDBusMessage  *message);
+                                                              GDBusMessage  *message,
+                                                              gboolean sync);
 G_END_DECLS
 
 #endif /* __G_KDBUSFAKEDAEMON_H__ */