[sysprof] libsysprof: add vfunc to modify spawn arguments



commit c204081cc0b8c8753291e625ca98858d00de45f7
Author: Christian Hergert <chergert redhat com>
Date:   Tue May 21 21:57:36 2019 -0700

    libsysprof: add vfunc to modify spawn arguments

 src/libsysprof/sysprof-local-profiler.c | 80 +++++++++++++++++++++++++--------
 src/libsysprof/sysprof-source.c         | 13 ++++++
 src/libsysprof/sysprof-source.h         | 19 +++++++-
 3 files changed, 92 insertions(+), 20 deletions(-)
---
diff --git a/src/libsysprof/sysprof-local-profiler.c b/src/libsysprof/sysprof-local-profiler.c
index bcf57eb..3413d44 100644
--- a/src/libsysprof/sysprof-local-profiler.c
+++ b/src/libsysprof/sysprof-local-profiler.c
@@ -467,6 +467,25 @@ sysprof_local_profiler_finish_startup (SysprofLocalProfiler *self)
     sysprof_local_profiler_stop (SYSPROF_PROFILER (self));
 }
 
+static void
+sysprof_local_profiler_wait_cb (GObject      *object,
+                                GAsyncResult *result,
+                                gpointer      user_data)
+{
+  GSubprocess *subprocess = (GSubprocess *)object;
+  g_autoptr(SysprofLocalProfiler) self = user_data;
+  g_autoptr(GError) error = NULL;
+
+  g_assert (G_IS_SUBPROCESS (subprocess));
+  g_assert (G_IS_ASYNC_RESULT (result));
+  g_assert (SYSPROF_IS_LOCAL_PROFILER (self));
+
+  if (!g_subprocess_wait_finish (subprocess, result, &error))
+    g_warning ("Wait on subprocess failed: %s", error->message);
+
+  sysprof_local_profiler_stop (SYSPROF_PROFILER (self));
+}
+
 static void
 sysprof_local_profiler_authorize_cb (GObject      *object,
                                      GAsyncResult *result,
@@ -521,7 +540,10 @@ sysprof_local_profiler_authorize_cb (GObject      *object,
 
   if (priv->spawn && priv->spawn_argv && priv->spawn_argv[0])
     {
-      g_autoptr(GPtrArray) ar = g_ptr_array_new_with_free_func (g_free);
+      g_autoptr(GPtrArray) env = g_ptr_array_new_with_free_func (g_free);
+      g_autoptr(GPtrArray) argv = g_ptr_array_new_with_free_func (g_free);
+      g_autoptr(GSubprocessLauncher) launcher = NULL;
+      g_autoptr(GSubprocess) subprocess = NULL;
       GPid pid;
 
       if (priv->spawn_inherit_environ)
@@ -529,41 +551,61 @@ sysprof_local_profiler_authorize_cb (GObject      *object,
           gchar **environ = g_get_environ ();
 
           for (guint i = 0; environ[i]; i++)
-            g_ptr_array_add (ar, environ[i]);
+            g_ptr_array_add (env, environ[i]);
           g_free (environ);
         }
 
       if (priv->spawn_env)
         {
           for (guint i = 0; priv->spawn_env[i]; i++)
-            g_ptr_array_add (ar, g_strdup (priv->spawn_env[i]));
+            g_ptr_array_add (env, g_strdup (priv->spawn_env[i]));
+        }
+
+      g_ptr_array_add (env, NULL);
+
+      launcher = g_subprocess_launcher_new (0);
+      g_subprocess_launcher_set_environ (launcher, (gchar **)env->pdata);
+      g_subprocess_launcher_set_cwd (launcher, g_get_home_dir ());
+
+      if (priv->spawn_argv)
+        {
+          for (guint i = 0; priv->spawn_argv[i]; i++)
+            g_ptr_array_add (argv, g_strdup (priv->spawn_argv[i]));
         }
 
-      g_ptr_array_add (ar, NULL);
-
-      if (!g_spawn_async (g_get_home_dir (),
-                          priv->spawn_argv,
-                          (gchar **)ar->pdata,
-                          (G_SPAWN_SEARCH_PATH |
-                           G_SPAWN_STDOUT_TO_DEV_NULL |
-                           G_SPAWN_STDOUT_TO_DEV_NULL),
-                          NULL,
-                          NULL,
-                          &pid,
-                          &error))
-        g_ptr_array_add (priv->failures, g_steal_pointer (&error));
+      for (guint i = 0; i < priv->sources->len; i++)
+        {
+          SysprofSource *source = g_ptr_array_index (priv->sources, i);
+          sysprof_source_modify_spawn (source, launcher, argv);
+        }
+
+      g_ptr_array_add (argv, NULL);
+
+      if (!(subprocess = g_subprocess_launcher_spawnv (launcher,
+                                                       (const gchar * const *)argv->pdata,
+                                                       &error)))
+        {
+          g_ptr_array_add (priv->failures, g_steal_pointer (&error));
+        }
       else
-        g_array_append_val (priv->pids, pid);
+        {
+          const gchar *ident = g_subprocess_get_identifier (subprocess);
+          pid = atoi (ident);
+          g_array_append_val (priv->pids, pid);
+          g_subprocess_wait_async (subprocess,
+                                   NULL,
+                                   sysprof_local_profiler_wait_cb,
+                                   g_object_ref (self));
+        }
     }
 
   for (guint i = 0; i < priv->sources->len; i++)
     {
       SysprofSource *source = g_ptr_array_index (priv->sources, i);
-      guint j;
 
       if (priv->whole_system == FALSE)
         {
-          for (j = 0; j < priv->pids->len; j++)
+          for (guint j = 0; j < priv->pids->len; j++)
             {
               GPid pid = g_array_index (priv->pids, GPid, j);
 
diff --git a/src/libsysprof/sysprof-source.c b/src/libsysprof/sysprof-source.c
index cece9c3..420cf14 100644
--- a/src/libsysprof/sysprof-source.c
+++ b/src/libsysprof/sysprof-source.c
@@ -139,3 +139,16 @@ sysprof_source_stop (SysprofSource *self)
   if (SYSPROF_SOURCE_GET_IFACE (self)->stop)
     SYSPROF_SOURCE_GET_IFACE (self)->stop (self);
 }
+
+void
+sysprof_source_modify_spawn (SysprofSource       *self,
+                             GSubprocessLauncher *launcher,
+                             GPtrArray           *argv)
+{
+  g_return_if_fail (SYSPROF_IS_SOURCE (self));
+  g_return_if_fail (G_IS_SUBPROCESS_LAUNCHER (launcher));
+  g_return_if_fail (argv != NULL);
+
+  if (SYSPROF_SOURCE_GET_IFACE (self)->modify_spawn)
+    SYSPROF_SOURCE_GET_IFACE (self)->modify_spawn (self, launcher, argv);
+}
diff --git a/src/libsysprof/sysprof-source.h b/src/libsysprof/sysprof-source.h
index 896d237..31c8989 100644
--- a/src/libsysprof/sysprof-source.h
+++ b/src/libsysprof/sysprof-source.h
@@ -24,7 +24,7 @@
 # error "Only <sysprof.h> can be included directly."
 #endif
 
-#include <glib-object.h>
+#include <gio/gio.h>
 
 #include "sysprof-capture-writer.h"
 
@@ -119,6 +119,19 @@ struct _SysprofSourceInterface
    * sysprof_source_emit_finished() must be called from the main-thread.
    */
   void (*stop) (SysprofSource *self);
+
+  /**
+   * SysprofSource::modify-spawn:
+   * @self: a #SysprofSource
+   * @launcher: a #GSubprocessLauncher
+   * @argv: (element-type utf8): arguments for spawning
+   *
+   * Allows the source to modify the launcher or argv before the
+   * process is spawned.
+   */
+  void (*modify_spawn) (SysprofSource       *self,
+                        GSubprocessLauncher *launcher,
+                        GPtrArray           *argv);
 };
 
 SYSPROF_AVAILABLE_IN_ALL
@@ -142,5 +155,9 @@ SYSPROF_AVAILABLE_IN_ALL
 void     sysprof_source_start         (SysprofSource        *self);
 SYSPROF_AVAILABLE_IN_ALL
 void     sysprof_source_stop          (SysprofSource        *self);
+SYSPROF_AVAILABLE_IN_ALL
+void     sysprof_source_modify_spawn  (SysprofSource        *self,
+                                       GSubprocessLauncher  *launcher,
+                                       GPtrArray            *argv);
 
 G_END_DECLS


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