profiler: preroll authorization before starting

This helps some annoying cases where we keep checking over and over for
each CPU, procfile, etc during startup.

It makes the tool less useful on systems without D-Bus, but let's be
honest, profiling is a Linux only game for Sysprof.
This commit is contained in:
Christian Hergert
2021-02-24 14:01:01 -08:00
parent 4777e74862
commit 143554c68e

View File

@ -535,61 +535,18 @@ sysprof_local_profiler_wait_cb (GObject *object,
}
static void
sysprof_local_profiler_start (SysprofProfiler *profiler)
sysprof_local_profiler_start_after_auth (SysprofLocalProfiler *self)
{
SysprofLocalProfiler *self = (SysprofLocalProfiler *)profiler;
SysprofLocalProfilerPrivate *priv = sysprof_local_profiler_get_instance_private (self);
g_autoptr(SysprofControlSource) control_source = NULL;
g_autofree gchar *keydata = NULL;
g_autoptr(GError) error = NULL;
g_autoptr(GKeyFile) keyfile = NULL;
gsize keylen = 0;
g_return_if_fail (SYSPROF_IS_LOCAL_PROFILER (self));
g_return_if_fail (priv->is_running == FALSE);
g_return_if_fail (priv->is_stopping == FALSE);
g_return_if_fail (priv->is_starting == FALSE);
g_clear_pointer (&priv->timer, g_timer_destroy);
g_object_notify (G_OBJECT (self), "elapsed");
control_source = sysprof_control_source_new ();
sysprof_profiler_add_source (SYSPROF_PROFILER (self), SYSPROF_SOURCE (control_source));
g_assert (SYSPROF_IS_LOCAL_PROFILER (self));
keyfile = g_key_file_new ();
if (priv->writer == NULL)
{
SysprofCaptureWriter *writer;
int fd;
if ((-1 == (fd = sysprof_memfd_create ("[sysprof]"))) ||
(NULL == (writer = sysprof_capture_writer_new_from_fd (fd, 0))))
{
const GError werror = {
G_FILE_ERROR,
g_file_error_from_errno (errno),
(gchar *)g_strerror (errno)
};
if (fd != -1)
close (fd);
sysprof_profiler_emit_failed (SYSPROF_PROFILER (self), &werror);
return;
}
sysprof_profiler_set_writer (SYSPROF_PROFILER (self), writer);
g_clear_pointer (&writer, sysprof_capture_writer_unref);
}
priv->is_running = TRUE;
priv->is_starting = TRUE;
if (priv->failures->len > 0)
g_ptr_array_remove_range (priv->failures, 0, priv->failures->len);
g_key_file_set_boolean (keyfile, "profiler", "whole-system", priv->whole_system);
if (priv->pids->len > 0)
g_key_file_set_integer_list (keyfile, "profiler", "pids",
@ -708,6 +665,87 @@ sysprof_local_profiler_start (SysprofProfiler *profiler)
sysprof_local_profiler_finish_startup (self);
}
static void
sysprof_local_profiler_preroll_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
{
SysprofHelpers *helpers = (SysprofHelpers *)object;
g_autoptr(SysprofLocalProfiler) self = user_data;
g_autoptr(GError) error = NULL;
g_assert (SYSPROF_IS_HELPERS (helpers));
g_assert (SYSPROF_IS_LOCAL_PROFILER (self));
/* For almost everything at this point, we need to have authorization
* to the helper daemon. So if this fails, just assume we are going to
* fail in general. It doesn't really help us to optimize for the case
* of user-space only profiling since we are rarely used for that.
*/
if (!sysprof_helpers_authorize_finish (helpers, result, &error))
sysprof_profiler_emit_failed (SYSPROF_PROFILER (self), error);
else
sysprof_local_profiler_start_after_auth (self);
}
static void
sysprof_local_profiler_start (SysprofProfiler *profiler)
{
SysprofLocalProfiler *self = (SysprofLocalProfiler *)profiler;
SysprofLocalProfilerPrivate *priv = sysprof_local_profiler_get_instance_private (self);
g_autoptr(SysprofControlSource) control_source = NULL;
g_return_if_fail (SYSPROF_IS_LOCAL_PROFILER (self));
g_return_if_fail (priv->is_running == FALSE);
g_return_if_fail (priv->is_stopping == FALSE);
g_return_if_fail (priv->is_starting == FALSE);
g_clear_pointer (&priv->timer, g_timer_destroy);
g_object_notify (G_OBJECT (self), "elapsed");
control_source = sysprof_control_source_new ();
sysprof_profiler_add_source (SYSPROF_PROFILER (self), SYSPROF_SOURCE (control_source));
if (priv->writer == NULL)
{
SysprofCaptureWriter *writer;
int fd;
if ((-1 == (fd = sysprof_memfd_create ("[sysprof]"))) ||
(NULL == (writer = sysprof_capture_writer_new_from_fd (fd, 0))))
{
const GError werror = {
G_FILE_ERROR,
g_file_error_from_errno (errno),
(gchar *)g_strerror (errno)
};
if (fd != -1)
close (fd);
sysprof_profiler_emit_failed (SYSPROF_PROFILER (self), &werror);
return;
}
sysprof_profiler_set_writer (SYSPROF_PROFILER (self), writer);
g_clear_pointer (&writer, sysprof_capture_writer_unref);
}
priv->is_running = TRUE;
priv->is_starting = TRUE;
if (priv->failures->len > 0)
g_ptr_array_remove_range (priv->failures, 0, priv->failures->len);
/* Start by prefolling our authorization so that future calls are cheap */
sysprof_helpers_authorize_async (sysprof_helpers_get_default (),
NULL,
sysprof_local_profiler_preroll_cb,
g_object_ref (self));
}
static void
sysprof_local_profiler_set_writer (SysprofProfiler *profiler,
SysprofCaptureWriter *writer)