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
This commit is contained in:
Christian Hergert
2025-01-28 13:29:53 -08:00
parent 72df41485d
commit 3ed3d8e620
10 changed files with 187 additions and 44 deletions

View File

@ -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");

View File

@ -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)))

View File

@ -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);
}

View File

@ -24,12 +24,15 @@
#include <sysprof.h>
#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

View File

@ -23,6 +23,7 @@
#include <json-glib/json-glib.h>
#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);
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -20,7 +20,11 @@
#include "config.h"
#include <fcntl.h>
#include <errno.h>
#include <glib/gi18n.h>
#include <glib/gstdio.h>
#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;
}

View File

@ -25,6 +25,7 @@
#include <sysprof.h>
#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