[sysprof] libsysprof: use SYSPROF_TRACE_FD env var when spawning



commit 3321308c4af7e0dca7213bcb9f31ffe66d1de176
Author: Christian Hergert <chergert redhat com>
Date:   Tue May 21 21:58:24 2019 -0700

    libsysprof: use SYSPROF_TRACE_FD env var when spawning
    
    This avoids connecting to the bus which is racey, and instead just hands
    the FD off to the subprocess.

 src/libsysprof/sysprof-proxy-source.c | 70 ++++++++++++++++++++++++++++++-----
 1 file changed, 60 insertions(+), 10 deletions(-)
---
diff --git a/src/libsysprof/sysprof-proxy-source.c b/src/libsysprof/sysprof-proxy-source.c
index 6d95744..f47a37d 100644
--- a/src/libsysprof/sysprof-proxy-source.c
+++ b/src/libsysprof/sysprof-proxy-source.c
@@ -149,7 +149,7 @@ sysprof_proxy_source_take_monitor (SysprofProxySource *self,
   g_assert (SYSPROF_IS_PROXY_SOURCE (self));
   g_assert (monitor != NULL);
   g_assert (monitor->self == self);
-  g_assert (G_IS_DBUS_CONNECTION (monitor->bus));
+  g_assert (monitor->bus == NULL || G_IS_DBUS_CONNECTION (monitor->bus));
 
   if (g_cancellable_is_cancelled (self->cancellable))
     monitor_free (monitor);
@@ -200,7 +200,7 @@ sysprof_proxy_source_monitor (SysprofProxySource *self,
   gint handle;
 
   g_assert (SYSPROF_IS_PROXY_SOURCE (self));
-  g_assert (G_IS_DBUS_CONNECTION (self));
+  g_assert (G_IS_DBUS_CONNECTION (bus));
   g_assert (bus_name != NULL);
 
   if (g_cancellable_is_cancelled (self->cancellable))
@@ -397,13 +397,31 @@ sysprof_proxy_source_cat (SysprofProxySource   *self,
     }
 }
 
+static void
+sysprof_proxy_source_complete_monitor (SysprofProxySource *self,
+                                       Monitor            *monitor)
+{
+  g_autoptr(SysprofCaptureReader) reader = NULL;
+  g_autoptr(GError) error = NULL;
+
+  g_assert (SYSPROF_IS_PROXY_SOURCE (self));
+  g_assert (monitor != NULL);
+  g_assert (monitor->self == self);
+
+  g_print ("completing with FD: %d\n", monitor->fd);
+
+  if (!(reader = sysprof_capture_reader_new_from_fd (steal_fd (&monitor->fd), &error)))
+    g_warning ("Failed to load reader from peer FD: %s", error->message);
+  else
+    sysprof_proxy_source_cat (self, reader);
+}
+
 static void
 sysprof_proxy_source_stop_cb (GObject      *object,
                               GAsyncResult *result,
                               gpointer      user_data)
 {
   GDBusConnection *bus = (GDBusConnection *)object;
-  g_autoptr(SysprofCaptureReader) reader = NULL;
   g_autoptr(Monitor) monitor = user_data;
   g_autoptr(GVariant) reply = NULL;
   g_autoptr(GError) error = NULL;
@@ -417,12 +435,7 @@ sysprof_proxy_source_stop_cb (GObject      *object,
   reply = g_dbus_connection_call_finish (bus, result, &error);
   monitor->needs_stop = FALSE;
 
-  /* TODO: Read back memfd containing data from peer */
-
-  if (!(reader = sysprof_capture_reader_new_from_fd (steal_fd (&monitor->fd), &error)))
-    g_warning ("Failed to load reader from peer FD: %s", error->message);
-  else
-    sysprof_proxy_source_cat (self, reader);
+  sysprof_proxy_source_complete_monitor (self, monitor);
 
   self->stopping_count--;
 
@@ -463,7 +476,7 @@ sysprof_proxy_source_stop (SysprofSource *source)
         }
       else
         {
-          /* Do nothing, as we never got the data setup */
+          sysprof_proxy_source_complete_monitor (self, monitor);
         }
     }
 
@@ -486,6 +499,39 @@ sysprof_proxy_source_add_pid (SysprofSource *source,
   g_array_append_val (self->pids, pid);
 }
 
+static void
+sysprof_proxy_source_modify_spawn (SysprofSource       *source,
+                                   GSubprocessLauncher *launcher,
+                                   GPtrArray           *argv)
+{
+  SysprofProxySource *self = (SysprofProxySource *)source;
+  gchar fdstr[12];
+  Monitor *monitor;
+  gint fd;
+
+  g_assert (SYSPROF_IS_PROXY_SOURCE (self));
+  g_assert (G_IS_SUBPROCESS_LAUNCHER (launcher));
+  g_assert (argv != NULL);
+
+  /* We need to create a new FD for the peer process to write
+   * to and notify it via SYSPROF_TRACE_FD. We will largely
+   * ignore things until the capture has finished.
+   */
+
+  if (-1 == (fd = sysprof_memfd_create ("[sysprof-proxy-capture]")))
+    return;
+
+  monitor = g_slice_new0 (Monitor);
+  monitor->self = g_object_ref (self);
+  monitor->fd = dup (fd);
+
+  g_snprintf (fdstr, sizeof fdstr, "%d", fd);
+  g_subprocess_launcher_setenv (launcher, "SYSPROF_TRACE_FD", fdstr, TRUE);
+  g_subprocess_launcher_take_fd (launcher, fd, fd);
+
+  sysprof_proxy_source_take_monitor (self, g_steal_pointer (&monitor));
+}
+
 static void
 source_iface_init (SysprofSourceInterface *iface)
 {
@@ -495,6 +541,7 @@ source_iface_init (SysprofSourceInterface *iface)
   iface->get_is_ready = sysprof_proxy_source_get_is_ready;
   iface->stop = sysprof_proxy_source_stop;
   iface->start = sysprof_proxy_source_start;
+  iface->modify_spawn = sysprof_proxy_source_modify_spawn;
 }
 
 G_DEFINE_TYPE_WITH_CODE (SysprofProxySource, sysprof_proxy_source, G_TYPE_OBJECT,
@@ -543,6 +590,9 @@ sysprof_proxy_source_new (GBusType     bus_type,
   g_return_val_if_fail (bus_name != NULL, NULL);
   g_return_val_if_fail (object_path != NULL, NULL);
 
+  if (bus_name && !*bus_name)
+    bus_name = NULL;
+
   self = g_object_new (SYSPROF_TYPE_PROXY_SOURCE, NULL);
   self->bus_type = bus_type;
   self->bus_name = g_strdup (bus_name);


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