From 3ed3d8e620cb426ac20fb2e8ec70c31a20391567 Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Tue, 28 Jan 2025 13:29:53 -0800 Subject: [PATCH] sysprof/greeter: apply default recording template to loader This ensures that the document loader can apply settings from the recording template (thusly applying future options such as debuginfod or extra debug directories). Related: #130 --- src/sysprof/sysprof-application.c | 8 ++- src/sysprof/sysprof-greeter.c | 17 ++--- src/sysprof/sysprof-recording-pad.c | 31 +++++++-- src/sysprof/sysprof-recording-pad.h | 5 +- src/sysprof/sysprof-recording-template.c | 55 +++++++++++++++- src/sysprof/sysprof-recording-template.h | 3 + src/sysprof/sysprof-util.c | 6 ++ src/sysprof/sysprof-util.h | 3 +- src/sysprof/sysprof-window.c | 81 ++++++++++++++++++++---- src/sysprof/sysprof-window.h | 22 ++++--- 10 files changed, 187 insertions(+), 44 deletions(-) diff --git a/src/sysprof/sysprof-application.c b/src/sysprof/sysprof-application.c index c3334d95..0f430836 100644 --- a/src/sysprof/sysprof-application.c +++ b/src/sysprof/sysprof-application.c @@ -24,6 +24,7 @@ #include "sysprof-application.h" #include "sysprof-credits.h" #include "sysprof-greeter.h" +#include "sysprof-recording-template.h" #include "sysprof-window.h" struct _SysprofApplication @@ -67,12 +68,15 @@ sysprof_application_open (GApplication *app, int n_files, const char *hint) { + g_autoptr(SysprofRecordingTemplate) template = NULL; g_assert (SYSPROF_IS_APPLICATION (app)); g_assert (files != NULL || n_files == 0); + template = sysprof_recording_template_new_from_file (NULL, NULL); + for (guint i = 0; i < n_files; i++) - sysprof_window_open (SYSPROF_APPLICATION (app), files[i]); + sysprof_window_open (SYSPROF_APPLICATION (app), template, files[i]); } static int @@ -147,7 +151,7 @@ sysprof_about (GSimpleAction *action, g_assert (variant == NULL); windows = gtk_application_get_windows (app); - + if (windows == NULL) { g_warning ("No windows found to show about dialog"); diff --git a/src/sysprof/sysprof-greeter.c b/src/sysprof/sysprof-greeter.c index 6dd975b1..caec226d 100644 --- a/src/sysprof/sysprof-greeter.c +++ b/src/sysprof/sysprof-greeter.c @@ -32,6 +32,7 @@ #include "sysprof-recording-pad.h" #include "sysprof-recording-template.h" #include "sysprof-stack-size.h" +#include "sysprof-util.h" #include "sysprof-window.h" G_DEFINE_AUTOPTR_CLEANUP_FUNC (SysprofCaptureWriter, sysprof_capture_writer_unref) @@ -63,12 +64,6 @@ struct _SysprofGreeter GtkLabel *user_stacks_caption; }; -static GFile * -get_state_file (void) -{ - return g_file_new_build_filename (g_get_user_data_dir (), APP_ID_S, "recording-template.json", NULL); -} - static GObject * sysprof_greeter_get_internal_child (GtkBuildable *buildable, GtkBuilder *builder, @@ -192,7 +187,7 @@ sysprof_greeter_record_cb (GObject *object, } else { - GtkWidget *pad = sysprof_recording_pad_new (recording); + GtkWidget *pad = sysprof_recording_pad_new (recording, self->recording_template); gtk_window_present (GTK_WINDOW (pad)); } @@ -221,7 +216,7 @@ sysprof_greeter_create_profiler (SysprofGreeter *self, if (!(profiler = sysprof_recording_template_apply (self->recording_template, error))) return NULL; - state_file = get_state_file (); + state_file = _get_default_state_file (); dir = g_file_get_parent (state_file); if (!g_file_query_exists (dir, NULL)) @@ -353,7 +348,9 @@ sysprof_greeter_select_file_action (GtkWidget *widget, const char *action_name, GVariant *param) { - sysprof_window_open_file (GTK_WINDOW (widget)); + SysprofGreeter *self = SYSPROF_GREETER (widget); + + sysprof_window_open_file (GTK_WINDOW (widget), self->recording_template); } static char * @@ -580,7 +577,7 @@ static void sysprof_greeter_init (SysprofGreeter *self) { g_autoptr(GListModel) power_profiles = sysprof_power_profiles_new (); - g_autoptr(GFile) state_file = get_state_file (); + g_autoptr(GFile) state_file = _get_default_state_file (); GtkListBoxRow *row; if (!(self->recording_template = sysprof_recording_template_new_from_file (state_file, NULL))) diff --git a/src/sysprof/sysprof-recording-pad.c b/src/sysprof/sysprof-recording-pad.c index f3b39c30..f9319f1c 100644 --- a/src/sysprof/sysprof-recording-pad.c +++ b/src/sysprof/sysprof-recording-pad.c @@ -29,18 +29,20 @@ struct _SysprofRecordingPad { - AdwWindow parent_instance; + AdwWindow parent_instance; - SysprofRecording *recording; + SysprofRecording *recording; + SysprofRecordingTemplate *template; - GtkButton *stop_button; + GtkButton *stop_button; - guint closed : 1; + guint closed : 1; }; enum { PROP_0, PROP_RECORDING, + PROP_TEMPLATE, N_PROPS }; @@ -124,7 +126,7 @@ sysprof_recording_pad_wait_cb (GObject *object, else if (-1 != (fd = sysprof_recording_dup_fd (self->recording))) { lseek (fd, 0, SEEK_SET); - sysprof_window_open_fd (SYSPROF_APPLICATION_DEFAULT, fd); + sysprof_window_open_fd (SYSPROF_APPLICATION_DEFAULT, self->template, fd); } if (!self->closed) @@ -154,6 +156,7 @@ sysprof_recording_pad_dispose (GObject *object) SysprofRecordingPad *self = (SysprofRecordingPad *)object; g_clear_object (&self->recording); + g_clear_object (&self->template); G_OBJECT_CLASS (sysprof_recording_pad_parent_class)->dispose (object); } @@ -172,6 +175,10 @@ sysprof_recording_pad_get_property (GObject *object, g_value_set_object (value, self->recording); break; + case PROP_TEMPLATE: + g_value_set_object (value, self->template); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -191,6 +198,10 @@ sysprof_recording_pad_set_property (GObject *object, self->recording = g_value_dup_object (value); break; + case PROP_TEMPLATE: + self->template = g_value_dup_object (value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -215,6 +226,11 @@ sysprof_recording_pad_class_init (SysprofRecordingPadClass *klass) SYSPROF_TYPE_RECORDING, (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + properties [PROP_TEMPLATE] = + g_param_spec_object ("template", NULL, NULL, + SYSPROF_TYPE_RECORDING_TEMPLATE, + (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + g_object_class_install_properties (object_class, N_PROPS, properties); gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/sysprof/sysprof-recording-pad.ui"); @@ -232,12 +248,15 @@ sysprof_recording_pad_init (SysprofRecordingPad *self) } GtkWidget * -sysprof_recording_pad_new (SysprofRecording *recording) +sysprof_recording_pad_new (SysprofRecording *recording, + SysprofRecordingTemplate *template) { g_return_val_if_fail (SYSPROF_IS_RECORDING (recording), NULL); + g_return_val_if_fail (!template || SYSPROF_IS_RECORDING_TEMPLATE (template), NULL); return g_object_new (SYSPROF_TYPE_RECORDING_PAD, "application", SYSPROF_APPLICATION_DEFAULT, "recording", recording, + "template", template, NULL); } diff --git a/src/sysprof/sysprof-recording-pad.h b/src/sysprof/sysprof-recording-pad.h index e7080ed2..edeffe10 100644 --- a/src/sysprof/sysprof-recording-pad.h +++ b/src/sysprof/sysprof-recording-pad.h @@ -24,12 +24,15 @@ #include +#include "sysprof-recording-template.h" + G_BEGIN_DECLS #define SYSPROF_TYPE_RECORDING_PAD (sysprof_recording_pad_get_type()) G_DECLARE_FINAL_TYPE (SysprofRecordingPad, sysprof_recording_pad, SYSPROF, RECORDING_PAD, AdwWindow) -GtkWidget *sysprof_recording_pad_new (SysprofRecording *recording); +GtkWidget *sysprof_recording_pad_new (SysprofRecording *recording, + SysprofRecordingTemplate *template); G_END_DECLS diff --git a/src/sysprof/sysprof-recording-template.c b/src/sysprof/sysprof-recording-template.c index 9ecbad8d..204dc2f9 100644 --- a/src/sysprof/sysprof-recording-template.c +++ b/src/sysprof/sysprof-recording-template.c @@ -23,6 +23,7 @@ #include #include "sysprof-recording-template.h" +#include "sysprof-util.h" #define DEFAULT_STACK_SIZE (4096*4) @@ -687,10 +688,14 @@ sysprof_recording_template_new_from_file (GFile *file, GError **error) { g_autoptr(JsonParser) parser = NULL; + g_autoptr(GFile) state_file = NULL; SysprofRecordingTemplate *self; JsonNode *root; - g_return_val_if_fail (G_IS_FILE (file), NULL); + g_return_val_if_fail (!file || G_IS_FILE (file), NULL); + + if (file == NULL) + file = state_file = _get_default_state_file (); parser = json_parser_new (); @@ -743,3 +748,51 @@ sysprof_recording_template_save (SysprofRecordingTemplate *self, return json_generator_to_stream (generator, G_OUTPUT_STREAM (stream), NULL, error); } + +SysprofDocumentLoader * +sysprof_recording_template_create_loader (SysprofRecordingTemplate *self, + int fd, + GError **error) +{ + g_autoptr(SysprofDocumentLoader) loader = NULL; + g_autoptr(SysprofMultiSymbolizer) multi = NULL; + g_autoptr(SysprofElfSymbolizer) elf = NULL; + + g_return_val_if_fail (SYSPROF_IS_RECORDING_TEMPLATE (self), NULL); + + if (!(loader = sysprof_document_loader_new_for_fd (fd, error))) + return NULL; + + multi = sysprof_multi_symbolizer_new (); + + elf = SYSPROF_ELF_SYMBOLIZER (sysprof_elf_symbolizer_new ()); + /* TODO: add extra-debug-directories property and use that to + * call sysprof_elf_symbolizer_set_external_debug_dirs(elf,...) + */ + + /* Add in order of priority */ + sysprof_multi_symbolizer_take (multi, sysprof_bundled_symbolizer_new ()); + sysprof_multi_symbolizer_take (multi, sysprof_kallsyms_symbolizer_new ()); + sysprof_multi_symbolizer_take (multi, SYSPROF_SYMBOLIZER (g_steal_pointer (&elf))); + sysprof_multi_symbolizer_take (multi, sysprof_jitmap_symbolizer_new ()); + + sysprof_document_loader_set_symbolizer (loader, SYSPROF_SYMBOLIZER (multi)); + +#if HAVE_DEBUGINFOD +#if 0 + /* TODO: add enable-debuginfod property. */ + if (self->enable_debuginfod) +#endif + { + g_autoptr(SysprofSymbolizer) debuginfod = NULL; + g_autoptr(GError) debuginfod_error = NULL; + + if (!(debuginfod = sysprof_debuginfod_symbolizer_new (&debuginfod_error))) + g_warning ("Failed to create debuginfod symbolizer: %s", debuginfod_error->message); + else + sysprof_multi_symbolizer_take (multi, g_steal_pointer (&debuginfod)); + } +#endif + + return g_steal_pointer (&loader); +} diff --git a/src/sysprof/sysprof-recording-template.h b/src/sysprof/sysprof-recording-template.h index f03bc639..dbaf96c1 100644 --- a/src/sysprof/sysprof-recording-template.h +++ b/src/sysprof/sysprof-recording-template.h @@ -43,5 +43,8 @@ SysprofRecordingTemplate *sysprof_recording_template_new_from_file (GFile gboolean sysprof_recording_template_save (SysprofRecordingTemplate *self, GFile *file, GError **error); +SysprofDocumentLoader *sysprof_recording_template_create_loader (SysprofRecordingTemplate *self, + int fd, + GError **error); G_END_DECLS diff --git a/src/sysprof/sysprof-util.c b/src/sysprof/sysprof-util.c index bb4c8b1c..070a6b55 100644 --- a/src/sysprof/sysprof-util.c +++ b/src/sysprof/sysprof-util.c @@ -66,3 +66,9 @@ _gtk_widget_hide_with_fade (GtkWidget *widget) g_memdup2 (&begin_time, sizeof begin_time), g_free); } + +GFile * +_get_default_state_file (void) +{ + return g_file_new_build_filename (g_get_user_data_dir (), APP_ID_S, "recording-template.json", NULL); +} diff --git a/src/sysprof/sysprof-util.h b/src/sysprof/sysprof-util.h index 53aa5cb4..6d577090 100644 --- a/src/sysprof/sysprof-util.h +++ b/src/sysprof/sysprof-util.h @@ -24,6 +24,7 @@ G_BEGIN_DECLS -void _gtk_widget_hide_with_fade (GtkWidget *widget); +void _gtk_widget_hide_with_fade (GtkWidget *widget); +GFile *_get_default_state_file (void); G_END_DECLS diff --git a/src/sysprof/sysprof-window.c b/src/sysprof/sysprof-window.c index 5fd6e9a1..e81e264b 100644 --- a/src/sysprof/sysprof-window.c +++ b/src/sysprof/sysprof-window.c @@ -20,7 +20,11 @@ #include "config.h" +#include +#include + #include +#include #include "sysprof-counters-section.h" #include "sysprof-cpu-section.h" @@ -34,6 +38,7 @@ #include "sysprof-memory-section.h" #include "sysprof-metadata-section.h" #include "sysprof-network-section.h" +#include "sysprof-pair.h" #include "sysprof-processes-section.h" #include "sysprof-samples-section.h" #include "sysprof-sidebar.h" @@ -133,7 +138,9 @@ sysprof_window_open_file_cb (GObject *object, gpointer user_data) { GtkFileDialog *dialog = (GtkFileDialog *)object; - g_autoptr(GtkWindow) transient_for = user_data; + g_autoptr(SysprofRecordingTemplate) template = NULL; + g_autoptr(GtkWindow) transient_for = NULL; + g_autoptr(SysprofPair) pair = user_data; g_autoptr(GError) error = NULL; g_autoptr(GFile) file = NULL; @@ -141,11 +148,19 @@ sysprof_window_open_file_cb (GObject *object, g_assert (G_IS_ASYNC_RESULT (result)); g_assert (!transient_for || GTK_IS_WINDOW (transient_for)); + g_object_get (pair, + "first", &transient_for, + "second", &template, + NULL); + + g_assert (!transient_for || GTK_IS_WIDGET (transient_for)); + g_assert (!template || SYSPROF_IS_RECORDING_TEMPLATE (template)); + if ((file = gtk_file_dialog_open_finish (dialog, result, &error))) { if (g_file_is_native (file)) { - sysprof_window_open (SYSPROF_APPLICATION_DEFAULT, file); + sysprof_window_open (SYSPROF_APPLICATION_DEFAULT, template, file); if (transient_for && !SYSPROF_IS_WINDOW (transient_for)) gtk_window_destroy (transient_for); @@ -168,7 +183,8 @@ sysprof_window_open_file_cb (GObject *object, } void -sysprof_window_open_file (GtkWindow *parent) +sysprof_window_open_file (GtkWindow *parent, + SysprofRecordingTemplate *template) { g_autoptr(GtkFileDialog) dialog = NULL; g_autoptr(GtkFileFilter) filter = NULL; @@ -192,7 +208,10 @@ sysprof_window_open_file (GtkWindow *parent) parent, NULL, sysprof_window_open_file_cb, - parent ? g_object_ref (parent) : NULL); + g_object_new (SYSPROF_TYPE_PAIR, + "first", parent, + "second", template, + NULL)); } static void @@ -200,7 +219,12 @@ sysprof_window_open_capture_action (GtkWidget *widget, const char *action_name, GVariant *param) { - sysprof_window_open_file (GTK_WINDOW (widget)); + g_autoptr(SysprofRecordingTemplate) template = NULL; + + /* Open for default state file so we can apply settings */ + template = sysprof_recording_template_new_from_file (NULL, NULL); + + sysprof_window_open_file (GTK_WINDOW (widget), template); } static void @@ -780,25 +804,47 @@ sysprof_window_create (SysprofApplication *app, } void -sysprof_window_open (SysprofApplication *app, - GFile *file) +sysprof_window_open (SysprofApplication *app, + SysprofRecordingTemplate *template, + GFile *file) { g_autoptr(SysprofDocumentLoader) loader = NULL; + g_autoptr(SysprofRecordingTemplate) alt_template = NULL; + g_autoptr(GError) error = NULL; + g_autofd int fd = -1; SysprofWindow *self; + const char *path; g_return_if_fail (SYSPROF_IS_APPLICATION (app)); + g_return_if_fail (!template || SYSPROF_IS_RECORDING_TEMPLATE (template)); g_return_if_fail (G_IS_FILE (file)); - if (!g_file_is_native (file) || - !(loader = sysprof_document_loader_new (g_file_peek_path (file)))) + if (template == NULL) + template = alt_template = sysprof_recording_template_new (); + + if (!g_file_is_native (file)) { g_autofree char *uri = g_file_get_uri (file); g_warning ("Cannot open non-native file \"%s\"", uri); return; } + path = g_file_peek_path (file); + + if (-1 == (fd = open (path, O_RDONLY))) + { + int errsv = errno; + g_critical ("Failed to open %s: %s", path, g_strerror (errsv)); + return; + } + + if (!(loader = sysprof_recording_template_create_loader (template, fd, &error))) + { + g_critical ("Failed to create loader: %s", error->message); + return; + } + g_application_hold (G_APPLICATION (app)); - sysprof_window_apply_loader_settings (loader); self = sysprof_window_create (app, loader); sysprof_document_loader_load_async (loader, NULL, @@ -808,18 +854,25 @@ sysprof_window_open (SysprofApplication *app, } void -sysprof_window_open_fd (SysprofApplication *app, - int fd) +sysprof_window_open_fd (SysprofApplication *app, + SysprofRecordingTemplate *template, + int fd) { + g_autoptr(SysprofRecordingTemplate) alt_template = NULL; g_autoptr(SysprofDocumentLoader) loader = NULL; g_autoptr(GError) error = NULL; SysprofWindow *self; g_return_if_fail (SYSPROF_IS_APPLICATION (app)); + g_return_if_fail (!template || SYSPROF_IS_RECORDING_TEMPLATE (template)); + g_return_if_fail (fd > -1); - if (!(loader = sysprof_document_loader_new_for_fd (fd, &error))) + if (template == NULL) + template = alt_template = sysprof_recording_template_new (); + + if (!(loader = sysprof_recording_template_create_loader (template, fd, &error))) { - g_critical ("Failed to dup FD: %s", error->message); + g_critical ("Failed to create loader: %s", error->message); return; } diff --git a/src/sysprof/sysprof-window.h b/src/sysprof/sysprof-window.h index 4da9a635..fa44b0ec 100644 --- a/src/sysprof/sysprof-window.h +++ b/src/sysprof/sysprof-window.h @@ -25,6 +25,7 @@ #include #include "sysprof-application.h" +#include "sysprof-recording-template.h" #include "sysprof-session.h" G_BEGIN_DECLS @@ -33,14 +34,17 @@ G_BEGIN_DECLS G_DECLARE_FINAL_TYPE (SysprofWindow, sysprof_window, SYSPROF, WINDOW, AdwApplicationWindow) -GtkWidget *sysprof_window_new (SysprofApplication *app, - SysprofDocument *document); -void sysprof_window_open_file (GtkWindow *transient_for); -void sysprof_window_open (SysprofApplication *app, - GFile *file); -void sysprof_window_open_fd (SysprofApplication *app, - int fd); -SysprofDocument *sysprof_window_get_document (SysprofWindow *self); -SysprofSession *sysprof_window_get_session (SysprofWindow *self); +GtkWidget *sysprof_window_new (SysprofApplication *app, + SysprofDocument *document); +void sysprof_window_open_file (GtkWindow *transient_for, + SysprofRecordingTemplate *template); +void sysprof_window_open (SysprofApplication *app, + SysprofRecordingTemplate *template, + GFile *file); +void sysprof_window_open_fd (SysprofApplication *app, + SysprofRecordingTemplate *template, + int fd); +SysprofDocument *sysprof_window_get_document (SysprofWindow *self); +SysprofSession *sysprof_window_get_session (SysprofWindow *self); G_END_DECLS