From c204081cc0b8c8753291e625ca98858d00de45f7 Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Tue, 21 May 2019 21:57:36 -0700 Subject: [PATCH] libsysprof: add vfunc to modify spawn arguments --- src/libsysprof/sysprof-local-profiler.c | 78 +++++++++++++++++++------ src/libsysprof/sysprof-source.c | 13 +++++ src/libsysprof/sysprof-source.h | 19 +++++- 3 files changed, 91 insertions(+), 19 deletions(-) diff --git a/src/libsysprof/sysprof-local-profiler.c b/src/libsysprof/sysprof-local-profiler.c index bcf57eb3..3413d44b 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 (ar, NULL); + g_ptr_array_add (env, 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)); + 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])); + } + + 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 cece9c3a..420cf146 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 896d2372..31c89899 100644 --- a/src/libsysprof/sysprof-source.h +++ b/src/libsysprof/sysprof-source.h @@ -24,7 +24,7 @@ # error "Only can be included directly." #endif -#include +#include #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