From c38c1fb4b05d782f009aba0e7dec334f716cdd17 Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Mon, 7 Aug 2023 12:54:46 -0700 Subject: [PATCH] libsysprof: allow specifying phase for subprocess output This is helpful in that you can specify which phase of the capture the process should be run so that it's less likely to show up on profiles. --- src/libsysprof/meson.build | 1 + src/libsysprof/sysprof-recording.h | 7 ++ src/libsysprof/sysprof-subprocess-output.c | 86 ++++++++++++++++++++++ src/libsysprof/sysprof-subprocess-output.h | 34 +++++---- 4 files changed, 114 insertions(+), 14 deletions(-) diff --git a/src/libsysprof/meson.build b/src/libsysprof/meson.build index 5c62d4be..0c82bd2b 100644 --- a/src/libsysprof/meson.build +++ b/src/libsysprof/meson.build @@ -160,6 +160,7 @@ endif libsysprof_enum_headers = [ 'sysprof-callgraph.h', + 'sysprof-recording.h', ] libsysprof_enums = gnome.mkenums_simple('sysprof-enums', diff --git a/src/libsysprof/sysprof-recording.h b/src/libsysprof/sysprof-recording.h index e8b491f7..a0503ba0 100644 --- a/src/libsysprof/sysprof-recording.h +++ b/src/libsysprof/sysprof-recording.h @@ -28,6 +28,13 @@ G_BEGIN_DECLS #define SYSPROF_TYPE_RECORDING (sysprof_recording_get_type()) +typedef enum _SysprofRecordingPhase +{ + SYSPROF_RECORDING_PHASE_PREPARE = 1, + SYSPROF_RECORDING_PHASE_RECORD, + SYSPROF_RECORDING_PHASE_AUGMENT, +} SysprofRecordingPhase; + SYSPROF_AVAILABLE_IN_ALL G_DECLARE_FINAL_TYPE (SysprofRecording, sysprof_recording, SYSPROF, RECORDING, GObject) diff --git a/src/libsysprof/sysprof-subprocess-output.c b/src/libsysprof/sysprof-subprocess-output.c index dd944c76..c0b1fa2a 100644 --- a/src/libsysprof/sysprof-subprocess-output.c +++ b/src/libsysprof/sysprof-subprocess-output.c @@ -20,6 +20,7 @@ #include "config.h" +#include "sysprof-enums.h" #include "sysprof-instrument-private.h" #include "sysprof-recording-private.h" #include "sysprof-subprocess-output.h" @@ -35,6 +36,8 @@ struct _SysprofSubprocessOutput SysprofRecording *recording; GCancellable *cancellable; + + SysprofRecordingPhase phase; }; struct _SysprofSubprocessOutputClass @@ -47,6 +50,7 @@ enum { PROP_COMMAND_ARGV, PROP_COMMAND_ENVIRON, PROP_COMMAND_CWD, + PROP_PHASE, PROP_STDOUT_PATH, N_PROPS }; @@ -146,6 +150,9 @@ sysprof_subprocess_output_record (SysprofInstrument *instrument, g_assert (SYSPROF_IS_RECORDING (recording)); g_assert (G_IS_CANCELLABLE (cancellable)); + if (self->phase != SYSPROF_RECORDING_PHASE_RECORD) + return dex_future_new_for_boolean (TRUE); + g_set_object (&self->recording, recording); g_set_object (&self->cancellable, cancellable); @@ -155,6 +162,46 @@ sysprof_subprocess_output_record (SysprofInstrument *instrument, g_object_unref); } +static DexFuture * +sysprof_subprocess_output_prepare (SysprofInstrument *instrument, + SysprofRecording *recording) +{ + SysprofSubprocessOutput *self = (SysprofSubprocessOutput *)instrument; + + g_assert (SYSPROF_IS_SUBPROCESS_OUTPUT (self)); + g_assert (SYSPROF_IS_RECORDING (recording)); + + if (self->phase != SYSPROF_RECORDING_PHASE_PREPARE) + return dex_future_new_for_boolean (TRUE); + + g_set_object (&self->recording, recording); + + return dex_scheduler_spawn (NULL, 0, + sysprof_subprocess_output_record_fiber, + g_object_ref (self), + g_object_unref); +} + +static DexFuture * +sysprof_subprocess_output_augment (SysprofInstrument *instrument, + SysprofRecording *recording) +{ + SysprofSubprocessOutput *self = (SysprofSubprocessOutput *)instrument; + + g_assert (SYSPROF_IS_SUBPROCESS_OUTPUT (self)); + g_assert (SYSPROF_IS_RECORDING (recording)); + + if (self->phase != SYSPROF_RECORDING_PHASE_AUGMENT) + return dex_future_new_for_boolean (TRUE); + + g_set_object (&self->recording, recording); + + return dex_scheduler_spawn (NULL, 0, + sysprof_subprocess_output_record_fiber, + g_object_ref (self), + g_object_unref); +} + static void sysprof_subprocess_output_dispose (GObject *object) { @@ -192,6 +239,10 @@ sysprof_subprocess_output_get_property (GObject *object, g_value_set_boxed (value, sysprof_subprocess_output_get_command_environ (self)); break; + case PROP_PHASE: + g_value_set_enum (value, sysprof_subprocess_output_get_phase (self)); + break; + case PROP_STDOUT_PATH: g_value_set_string (value, sysprof_subprocess_output_get_stdout_path (self)); break; @@ -223,6 +274,10 @@ sysprof_subprocess_output_set_property (GObject *object, sysprof_subprocess_output_set_command_environ (self, g_value_get_boxed (value)); break; + case PROP_PHASE: + sysprof_subprocess_output_set_phase (self, g_value_get_enum (value)); + break; + case PROP_STDOUT_PATH: sysprof_subprocess_output_set_stdout_path (self, g_value_get_string (value)); break; @@ -242,7 +297,9 @@ sysprof_subprocess_output_class_init (SysprofSubprocessOutputClass *klass) object_class->get_property = sysprof_subprocess_output_get_property; object_class->set_property = sysprof_subprocess_output_set_property; + instrument_class->prepare = sysprof_subprocess_output_prepare; instrument_class->record = sysprof_subprocess_output_record; + instrument_class->augment = sysprof_subprocess_output_augment; properties[PROP_COMMAND_CWD] = g_param_spec_string ("command-cwd", NULL, NULL, @@ -259,6 +316,12 @@ sysprof_subprocess_output_class_init (SysprofSubprocessOutputClass *klass) G_TYPE_STRV, (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS)); + properties[PROP_PHASE] = + g_param_spec_enum ("phase", NULL, NULL, + SYSPROF_TYPE_RECORDING_PHASE, + SYSPROF_RECORDING_PHASE_PREPARE, + (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS)); + properties[PROP_STDOUT_PATH] = g_param_spec_string ("stdout-path", NULL, NULL, NULL, @@ -270,6 +333,7 @@ sysprof_subprocess_output_class_init (SysprofSubprocessOutputClass *klass) static void sysprof_subprocess_output_init (SysprofSubprocessOutput *self) { + self->phase = SYSPROF_RECORDING_PHASE_PREPARE; } const char * @@ -365,3 +429,25 @@ sysprof_subprocess_output_set_stdout_path (SysprofSubprocessOutput *self, if (g_set_str (&self->stdout_path, stdout_path)) g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_STDOUT_PATH]); } + +SysprofRecordingPhase +sysprof_subprocess_output_get_phase (SysprofSubprocessOutput *self) +{ + g_return_val_if_fail (SYSPROF_IS_SUBPROCESS_OUTPUT (self), 0); + + return self->phase; +} + +void +sysprof_subprocess_output_set_phase (SysprofSubprocessOutput *self, + SysprofRecordingPhase phase) +{ + g_return_if_fail (phase > 0); + g_return_if_fail (phase <= SYSPROF_RECORDING_PHASE_AUGMENT); + + if (phase == self->phase) + return; + + self->phase = phase; + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_PHASE]); +} diff --git a/src/libsysprof/sysprof-subprocess-output.h b/src/libsysprof/sysprof-subprocess-output.h index 176472dc..162d84eb 100644 --- a/src/libsysprof/sysprof-subprocess-output.h +++ b/src/libsysprof/sysprof-subprocess-output.h @@ -21,6 +21,7 @@ #pragma once #include "sysprof-instrument.h" +#include "sysprof-recording.h" G_BEGIN_DECLS @@ -33,29 +34,34 @@ typedef struct _SysprofSubprocessOutput SysprofSubprocessOutput; typedef struct _SysprofSubprocessOutputClass SysprofSubprocessOutputClass; SYSPROF_AVAILABLE_IN_ALL -GType sysprof_subprocess_output_get_type (void) G_GNUC_CONST; +GType sysprof_subprocess_output_get_type (void) G_GNUC_CONST; SYSPROF_AVAILABLE_IN_ALL -SysprofInstrument *sysprof_subprocess_output_new (void); +SysprofRecordingPhase sysprof_subprocess_output_get_phase (SysprofSubprocessOutput *self); SYSPROF_AVAILABLE_IN_ALL -const char *sysprof_subprocess_output_get_stdout_path (SysprofSubprocessOutput *self); +void sysprof_subprocess_output_set_phase (SysprofSubprocessOutput *self, + SysprofRecordingPhase phase); SYSPROF_AVAILABLE_IN_ALL -const char *sysprof_subprocess_output_get_command_cwd (SysprofSubprocessOutput *self); +SysprofInstrument *sysprof_subprocess_output_new (void); SYSPROF_AVAILABLE_IN_ALL -const char * const *sysprof_subprocess_output_get_command_argv (SysprofSubprocessOutput *self); +const char *sysprof_subprocess_output_get_stdout_path (SysprofSubprocessOutput *self); SYSPROF_AVAILABLE_IN_ALL -const char * const *sysprof_subprocess_output_get_command_environ (SysprofSubprocessOutput *self); +const char *sysprof_subprocess_output_get_command_cwd (SysprofSubprocessOutput *self); SYSPROF_AVAILABLE_IN_ALL -void sysprof_subprocess_output_set_stdout_path (SysprofSubprocessOutput *self, - const char *stdout_path); +const char * const *sysprof_subprocess_output_get_command_argv (SysprofSubprocessOutput *self); SYSPROF_AVAILABLE_IN_ALL -void sysprof_subprocess_output_set_command_cwd (SysprofSubprocessOutput *self, - const char *command_cwd); +const char * const *sysprof_subprocess_output_get_command_environ (SysprofSubprocessOutput *self); SYSPROF_AVAILABLE_IN_ALL -void sysprof_subprocess_output_set_command_argv (SysprofSubprocessOutput *self, - const char * const *command_argv); +void sysprof_subprocess_output_set_stdout_path (SysprofSubprocessOutput *self, + const char *stdout_path); SYSPROF_AVAILABLE_IN_ALL -void sysprof_subprocess_output_set_command_environ (SysprofSubprocessOutput *self, - const char * const *command_environ); +void sysprof_subprocess_output_set_command_cwd (SysprofSubprocessOutput *self, + const char *command_cwd); +SYSPROF_AVAILABLE_IN_ALL +void sysprof_subprocess_output_set_command_argv (SysprofSubprocessOutput *self, + const char * const *command_argv); +SYSPROF_AVAILABLE_IN_ALL +void sysprof_subprocess_output_set_command_environ (SysprofSubprocessOutput *self, + const char * const *command_environ); G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofSubprocessOutput, g_object_unref)