[sysprof] profiler: preroll authorization before starting



commit 143554c68e692a783aae4f9c19d76de34ee1d060
Author: Christian Hergert <chergert redhat com>
Date:   Wed Feb 24 14:01:01 2021 -0800

    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.

 src/libsysprof/sysprof-local-profiler.c | 128 +++++++++++++++++++++-----------
 1 file changed, 83 insertions(+), 45 deletions(-)
---
diff --git a/src/libsysprof/sysprof-local-profiler.c b/src/libsysprof/sysprof-local-profiler.c
index 2c126e3..7de1a35 100644
--- a/src/libsysprof/sysprof-local-profiler.c
+++ b/src/libsysprof/sysprof-local-profiler.c
@@ -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)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]