[sysprof/wip/chergert/control-fd: 9/11] libsysprof: implement D-Bus service for control FD



commit 7c250fc3bc549264c648a5a80b556680378809aa
Author: Christian Hergert <chergert redhat com>
Date:   Sat Feb 8 11:40:17 2020 -0800

    libsysprof: implement D-Bus service for control FD
    
    This still needs a way to coordinate the flush with the inferior.
    
    However, if the process exits, this gets some peices in place to mux those
    streams into the final write stream (meaning the subprocess can collect
    without any locking).

 src/libsysprof/meson.build              |   1 +
 src/libsysprof/sysprof-control-source.c | 128 ++++++++++++++++++++++++++++++--
 src/meson.build                         |   6 ++
 src/org.gnome.Sysprof3.Collector.xml    |  21 ++++++
 4 files changed, 151 insertions(+), 5 deletions(-)
---
diff --git a/src/libsysprof/meson.build b/src/libsysprof/meson.build
index d5603ea..ab0f100 100644
--- a/src/libsysprof/meson.build
+++ b/src/libsysprof/meson.build
@@ -78,6 +78,7 @@ libsysprof_private_sources = [
   'sysprof-podman.c',
   'sysprof-polkit.c',
   'sysprof-symbol-map.c',
+  ipc_collector_src,
   ipc_service_src,
   stackstash_sources,
   helpers_sources,
diff --git a/src/libsysprof/sysprof-control-source.c b/src/libsysprof/sysprof-control-source.c
index 89853a4..40193e8 100644
--- a/src/libsysprof/sysprof-control-source.c
+++ b/src/libsysprof/sysprof-control-source.c
@@ -22,18 +22,24 @@
 
 #include "config.h"
 
+#include <fcntl.h>
+#include <gio/gunixfdlist.h>
 #include <gio/gunixinputstream.h>
 #include <gio/gunixoutputstream.h>
 #include <sys/socket.h>
 #include <sys/types.h>
 
+#include "ipc-collector.h"
+
 #include "sysprof-control-source.h"
 
 struct _SysprofControlSource
 {
-  GObject          parent_instance;
-  GDBusConnection *conn;
-  GPtrArray       *files;
+  GObject               parent_instance;
+  IpcCollector         *collector;
+  GDBusConnection      *conn;
+  SysprofCaptureWriter *writer;
+  GPtrArray            *files;
 };
 
 static void source_iface_init (SysprofSourceInterface *iface);
@@ -41,6 +47,8 @@ static void source_iface_init (SysprofSourceInterface *iface);
 G_DEFINE_TYPE_WITH_CODE (SysprofControlSource, sysprof_control_source, G_TYPE_OBJECT,
                          G_IMPLEMENT_INTERFACE (SYSPROF_TYPE_SOURCE, source_iface_init))
 
+static SysprofSourceInterface *parent_iface;
+
 SysprofControlSource *
 sysprof_control_source_new (void)
 {
@@ -53,6 +61,7 @@ sysprof_control_source_finalize (GObject *object)
   SysprofControlSource *self = (SysprofControlSource *)object;
 
   g_clear_object (&self->conn);
+  g_clear_object (&self->collector);
   g_clear_pointer (&self->files, g_ptr_array_unref);
 
   G_OBJECT_CLASS (sysprof_control_source_parent_class)->finalize (object);
@@ -72,6 +81,44 @@ sysprof_control_source_init (SysprofControlSource *self)
   self->files = g_ptr_array_new_with_free_func (g_free);
 }
 
+static gboolean
+on_handle_create_writer_cb (IpcCollector          *collector,
+                            GDBusMethodInvocation *invocation,
+                            GUnixFDList           *in_fd_list,
+                            SysprofControlSource  *self)
+{
+  gchar writer_tmpl[] = "sysprof-collector-XXXXXX";
+  int fd;
+
+  g_assert (IPC_IS_COLLECTOR (collector));
+  g_assert (G_IS_DBUS_METHOD_INVOCATION (invocation));
+  g_assert (SYSPROF_IS_CONTROL_SOURCE (self));
+
+  fd = g_mkstemp_full (writer_tmpl, O_CLOEXEC, 0);
+
+  if (fd > -1)
+    {
+      g_autoptr(GUnixFDList) out_fd_list = g_unix_fd_list_new_from_array (&fd, 1);
+
+      if (out_fd_list != NULL)
+        {
+          g_ptr_array_add (self->files, g_strdup (writer_tmpl));
+          ipc_collector_complete_create_writer (collector,
+                                                g_steal_pointer (&invocation),
+                                                out_fd_list,
+                                                g_variant_new_handle (0));
+          return TRUE;
+        }
+    }
+
+  g_dbus_method_invocation_return_error (g_steal_pointer (&invocation),
+                                         G_DBUS_ERROR,
+                                         G_DBUS_ERROR_FAILED,
+                                         "Failed to create FD for writer");
+
+  return TRUE;
+}
+
 static void
 sysprof_control_source_modify_spawn (SysprofSource    *source,
                                      SysprofSpawnable *spawnable)
@@ -111,14 +158,85 @@ sysprof_control_source_modify_spawn (SysprofSource    *source,
 
   g_set_object (&self->conn, conn);
 
-  /* TODO */
-  //g_dbus_interface_skeleton_export (GDBusInterfaceSkeleton *interface_, GDBusConnection *connection, const 
gchar *object_path, GError **error)
+  self->collector = ipc_collector_skeleton_new ();
+
+  g_signal_connect_object (self->collector,
+                           "handle-create-writer",
+                           G_CALLBACK (on_handle_create_writer_cb),
+                           self,
+                           0);
+
+  g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (self->collector),
+                                    conn,
+                                    "/org/gnome/Sysprof3/Collector",
+                                    NULL);
 
   g_dbus_connection_start_message_processing (conn);
 }
 
+static void
+sysprof_control_source_stop (SysprofSource *source)
+{
+  SysprofControlSource *self = (SysprofControlSource *)source;
+
+  g_assert (SYSPROF_IS_CONTROL_SOURCE (self));
+
+  if (self->conn != NULL)
+    {
+      g_dbus_connection_close_sync (self->conn, NULL, NULL);
+      g_clear_object (&self->conn);
+    }
+
+  if (parent_iface->stop)
+    parent_iface->stop (source);
+}
+
+static void
+sysprof_control_source_set_writer (SysprofSource        *source,
+                                   SysprofCaptureWriter *writer)
+{
+  SysprofControlSource *self = (SysprofControlSource *)source;
+
+  g_assert (SYSPROF_IS_CONTROL_SOURCE (self));
+
+  g_clear_pointer (&self->writer, sysprof_capture_writer_unref);
+
+  if (writer != NULL)
+    self->writer = sysprof_capture_writer_ref (writer);
+}
+
+static void
+sysprof_control_source_supplement (SysprofSource        *source,
+                                   SysprofCaptureReader *reader)
+{
+  SysprofControlSource *self = (SysprofControlSource *)source;
+
+  g_assert (SYSPROF_IS_CONTROL_SOURCE (self));
+
+  for (guint i = 0; i < self->files->len; i++)
+    {
+      const gchar *filename = g_ptr_array_index (self->files, i);
+      int fd = open (filename, O_RDONLY);
+
+      /* TODO: We can't simply splice these until we've forced the process
+       * to flush the buffers (unless they've already exited).
+       */
+
+      if (fd > -1)
+        {
+          _sysprof_capture_writer_splice_from_fd (self->writer, fd, NULL);
+          close (fd);
+        }
+    }
+}
+
 static void
 source_iface_init (SysprofSourceInterface *iface)
 {
+  parent_iface = g_type_interface_peek_parent (iface);
+
+  iface->set_writer = sysprof_control_source_set_writer;
   iface->modify_spawn = sysprof_control_source_modify_spawn;
+  iface->stop = sysprof_control_source_stop;
+  iface->supplement = sysprof_control_source_supplement;
 }
diff --git a/src/meson.build b/src/meson.build
index f464cbb..91fad7e 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -19,6 +19,12 @@ ipc_service_src = gnome.gdbus_codegen('ipc-service',
          namespace: 'Ipc',
 )
 
+ipc_collector_src = gnome.gdbus_codegen('ipc-collector',
+           sources: 'org.gnome.Sysprof3.Collector.xml',
+  interface_prefix: 'org.gnome.Sysprof3.',
+         namespace: 'Ipc',
+)
+
 ipc_legacy_src = gnome.gdbus_codegen('ipc-legacy',
            sources: 'org.gnome.Sysprof2.xml',
   interface_prefix: 'org.gnome.',
diff --git a/src/org.gnome.Sysprof3.Collector.xml b/src/org.gnome.Sysprof3.Collector.xml
new file mode 100644
index 0000000..76a746f
--- /dev/null
+++ b/src/org.gnome.Sysprof3.Collector.xml
@@ -0,0 +1,21 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd";>
+<node>
+  <interface name="org.gnome.Sysprof3.Collector">
+    <!--
+      CreateWriter:
+      @fd: (out): a file-descriptor for capture writing
+
+      Creates a FD to use for capture writing. The Sysprof application
+      will mux all streams created using this API when the profiling has
+      completed.
+
+      The caller can close() the FD when it is no longer in use (or allow
+      SysprofCaptureWriter to close it when unref'd.
+    -->
+    <method name="CreateWriter">
+      <annotation name="org.gtk.GDBus.C.UnixFD" value="true"/>
+      <arg type="h" name="fd" direction="out"/>
+    </method>
+  </interface>
+</node>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]