diff --git a/src/libsysprof/sysprof-local-profiler.c b/src/libsysprof/sysprof-local-profiler.c index aa07c248..d57b45b5 100644 --- a/src/libsysprof/sysprof-local-profiler.c +++ b/src/libsysprof/sysprof-local-profiler.c @@ -73,6 +73,7 @@ typedef struct /* Arguments and environment variables for spawning */ gchar **spawn_argv; gchar **spawn_env; + gchar *spawn_cwd; /* State flags */ guint is_running : 1; @@ -118,6 +119,7 @@ enum { PROP_IS_RUNNING, PROP_SPAWN, PROP_SPAWN_ARGV, + PROP_SPAWN_CWD, PROP_SPAWN_ENV, PROP_SPAWN_INHERIT_ENVIRON, PROP_WHOLE_SYSTEM, @@ -341,6 +343,10 @@ sysprof_local_profiler_get_property (GObject *object, g_value_set_boxed (value, priv->spawn_argv); break; + case PROP_SPAWN_CWD: + g_value_set_string (value, priv->spawn_cwd); + break; + case PROP_SPAWN_ENV: g_value_set_boxed (value, priv->spawn_env); break; @@ -378,6 +384,11 @@ sysprof_local_profiler_set_property (GObject *object, priv->spawn_argv = g_value_dup_boxed (value); break; + case PROP_SPAWN_CWD: + g_free (priv->spawn_cwd); + priv->spawn_cwd = g_value_dup_string (value); + break; + case PROP_SPAWN_ENV: g_strfreev (priv->spawn_env); priv->spawn_env = g_value_dup_boxed (value); @@ -403,6 +414,7 @@ sysprof_local_profiler_class_init (SysprofLocalProfilerClass *klass) g_object_class_override_property (object_class, PROP_IS_RUNNING, "is-running"); g_object_class_override_property (object_class, PROP_SPAWN, "spawn"); g_object_class_override_property (object_class, PROP_SPAWN_ARGV, "spawn-argv"); + g_object_class_override_property (object_class, PROP_SPAWN_CWD, "spawn-cwd"); g_object_class_override_property (object_class, PROP_SPAWN_ENV, "spawn-env"); g_object_class_override_property (object_class, PROP_SPAWN_INHERIT_ENVIRON, "spawn-inherit-environ"); g_object_class_override_property (object_class, PROP_WHOLE_SYSTEM, "whole-system"); @@ -583,6 +595,7 @@ sysprof_local_profiler_authorize_cb (GObject *object, priv->pids->len); g_key_file_set_boolean (keyfile, "profiler", "spawn", priv->spawn); g_key_file_set_boolean (keyfile, "profiler", "spawn-inherit-environ", priv->spawn_inherit_environ); + g_key_file_set_string (keyfile, "profiler", "spawn-cwd", priv->spawn_cwd ? priv->spawn_cwd : ""); if (priv->spawn && priv->spawn_argv && priv->spawn_argv[0]) { @@ -614,6 +627,9 @@ sysprof_local_profiler_authorize_cb (GObject *object, sysprof_spawnable_set_environ (spawnable, (const gchar * const *)env->pdata); sysprof_spawnable_append_args (spawnable, (const gchar * const *)priv->spawn_argv); + if (priv->spawn_cwd != NULL) + sysprof_spawnable_set_cwd (spawnable, priv->spawn_cwd); + /* Save argv before modifying */ if (priv->spawn_argv != NULL) g_key_file_set_string_list (keyfile, @@ -996,6 +1012,7 @@ sysprof_local_profiler_new_replay (SysprofCaptureReader *reader) g_autoptr(SysprofLocalProfiler) self = NULL; g_autoptr(SysprofCaptureCursor) cursor = NULL; g_autoptr(GKeyFile) keyfile = NULL; + g_autofree gchar *cwd = NULL; g_auto(GStrv) argv = NULL; g_auto(GStrv) env = NULL; gboolean inherit; @@ -1018,10 +1035,16 @@ sysprof_local_profiler_new_replay (SysprofCaptureReader *reader) inherit = g_key_file_get_boolean (keyfile, "profiler", "spawn-inherit-environ", NULL); argv = g_key_file_get_string_list (keyfile, "profiler", "spawn-argv", NULL, NULL); env = g_key_file_get_string_list (keyfile, "profiler", "spawn-env", NULL, NULL); + cwd = g_key_file_get_string (keyfile, "profiler", "spawn-cwd", NULL); n_sources = g_key_file_get_integer (keyfile, "profiler", "n-sources", NULL); + /* Ignore empty string */ + if (cwd != NULL && *cwd == 0) + g_clear_pointer (&cwd, g_free); + sysprof_profiler_set_spawn (SYSPROF_PROFILER (self), spawn); sysprof_profiler_set_spawn_argv (SYSPROF_PROFILER (self), CSTRV (argv)); + sysprof_profiler_set_spawn_cwd (SYSPROF_PROFILER (self), cwd); sysprof_profiler_set_spawn_env (SYSPROF_PROFILER (self), CSTRV (env)); sysprof_profiler_set_spawn_inherit_environ (SYSPROF_PROFILER (self), inherit); diff --git a/src/libsysprof/sysprof-profiler.c b/src/libsysprof/sysprof-profiler.c index f6bce9cd..12fe8b5b 100644 --- a/src/libsysprof/sysprof-profiler.c +++ b/src/libsysprof/sysprof-profiler.c @@ -102,6 +102,13 @@ sysprof_profiler_default_init (SysprofProfilerInterface *iface) G_TYPE_STRV, (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + g_object_interface_install_property (iface, + g_param_spec_string ("spawn-cwd", + "Spawn Working Directory", + "The directory to spawn the application from", + NULL, + (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); + g_object_interface_install_property (iface, g_param_spec_boxed ("spawn-env", "Sysprofawn Environment", @@ -163,9 +170,17 @@ sysprof_profiler_get_spawn (SysprofProfiler *self) return spawn; } +void +sysprof_profiler_set_spawn_cwd (SysprofProfiler *self, + const gchar *spawn_cwd) +{ + g_return_if_fail (SYSPROF_IS_PROFILER (self)); + g_object_set (self, "spawn-cwd", spawn_cwd, NULL); +} + void sysprof_profiler_set_spawn (SysprofProfiler *self, - gboolean spawn) + gboolean spawn) { g_return_if_fail (SYSPROF_IS_PROFILER (self)); g_object_set (self, "spawn", !!spawn, NULL); diff --git a/src/libsysprof/sysprof-profiler.h b/src/libsysprof/sysprof-profiler.h index df9291e2..24735cdf 100644 --- a/src/libsysprof/sysprof-profiler.h +++ b/src/libsysprof/sysprof-profiler.h @@ -162,6 +162,9 @@ SYSPROF_AVAILABLE_IN_ALL void sysprof_profiler_set_spawn_env (SysprofProfiler *self, const gchar * const *spawn_env); SYSPROF_AVAILABLE_IN_ALL +void sysprof_profiler_set_spawn_cwd (SysprofProfiler *self, + const gchar *cwd); +SYSPROF_AVAILABLE_IN_ALL void sysprof_profiler_add_source (SysprofProfiler *self, SysprofSource *source); SYSPROF_AVAILABLE_IN_ALL diff --git a/src/libsysprof/sysprof-spawnable.c b/src/libsysprof/sysprof-spawnable.c index aca38651..c206f766 100644 --- a/src/libsysprof/sysprof-spawnable.c +++ b/src/libsysprof/sysprof-spawnable.c @@ -38,6 +38,7 @@ struct _SysprofSpawnable GArray *fds; GPtrArray *argv; gchar **environ; + gchar *cwd; gint next_fd; }; @@ -270,7 +271,11 @@ sysprof_spawnable_spawn (SysprofSpawnable *self, launcher = g_subprocess_launcher_new (0); g_subprocess_launcher_set_environ (launcher, self->environ); - g_subprocess_launcher_set_cwd (launcher, g_get_home_dir ()); + + if (self->cwd != NULL) + g_subprocess_launcher_set_cwd (launcher, self->cwd); + else + g_subprocess_launcher_set_cwd (launcher, g_get_home_dir ()); for (guint i = 0; i < self->fds->len; i++) { @@ -284,3 +289,16 @@ sysprof_spawnable_spawn (SysprofSpawnable *self, return g_subprocess_launcher_spawnv (launcher, argv, error); } + +void +sysprof_spawnable_set_cwd (SysprofSpawnable *self, + const gchar *cwd) +{ + g_return_if_fail (SYSPROF_IS_SPAWNABLE (self)); + + if (g_strcmp0 (cwd, self->cwd) != 0) + { + g_free (self->cwd); + self->cwd = g_strdup (cwd); + } +} diff --git a/src/libsysprof/sysprof-spawnable.h b/src/libsysprof/sysprof-spawnable.h index de8600e3..56be5141 100644 --- a/src/libsysprof/sysprof-spawnable.h +++ b/src/libsysprof/sysprof-spawnable.h @@ -47,6 +47,9 @@ SYSPROF_AVAILABLE_IN_ALL void sysprof_spawnable_append_args (SysprofSpawnable *self, const gchar * const *argv); SYSPROF_AVAILABLE_IN_ALL +void sysprof_spawnable_set_cwd (SysprofSpawnable *self, + const gchar *cwd); +SYSPROF_AVAILABLE_IN_ALL const gchar * const *sysprof_spawnable_get_argv (SysprofSpawnable *self); SYSPROF_AVAILABLE_IN_ALL const gchar * const *sysprof_spawnable_get_environ (SysprofSpawnable *self); diff --git a/src/tools/sysprof-cli.c b/src/tools/sysprof-cli.c index f77ab268..fa553487 100644 --- a/src/tools/sysprof-cli.c +++ b/src/tools/sysprof-cli.c @@ -233,6 +233,7 @@ main (gint argc, if (command != NULL || child_argv != NULL) { g_auto(GStrv) env = g_get_environ (); + g_autofree gchar *cwd = NULL; gint child_argc; if (child_argv != NULL) @@ -245,7 +246,10 @@ main (gint argc, return EXIT_FAILURE; } + cwd = g_get_current_dir (); + sysprof_profiler_set_spawn (profiler, TRUE); + sysprof_profiler_set_spawn_cwd (profiler, cwd); sysprof_profiler_set_spawn_argv (profiler, (const gchar * const *)child_argv); sysprof_profiler_set_spawn_env (profiler, (const gchar * const *)env); }