diff --git a/lib/sp-perf-counter.c b/lib/sp-perf-counter.c index d400d5f6..dd01539f 100644 --- a/lib/sp-perf-counter.c +++ b/lib/sp-perf-counter.c @@ -118,6 +118,10 @@ G_DEFINE_BOXED_TYPE (SpPerfCounter, (GBoxedCopyFunc)sp_perf_counter_ref, (GBoxedFreeFunc)sp_perf_counter_unref) +#if ENABLE_SYSPROFD +static GDBusConnection *shared_conn; +#endif + static gboolean perf_gsource_dispatch (GSource *source, GSourceFunc callback, @@ -413,16 +417,17 @@ static GDBusProxy * get_proxy (void) { static GDBusProxy *proxy; - GDBusConnection *bus = NULL; if (proxy != NULL) return g_object_ref (proxy); - bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL); - if (bus == NULL) + if (shared_conn == NULL) + shared_conn = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL); + + if (shared_conn == NULL) return NULL; - proxy = g_dbus_proxy_new_sync (bus, + proxy = g_dbus_proxy_new_sync (shared_conn, (G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START_AT_CONSTRUCTION), @@ -490,8 +495,125 @@ get_authorized_proxy (void) return NULL; } + + +static void +sp_perf_counter_acquire_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + g_autoptr(GTask) task = user_data; + GPermission *permission = (GPermission *)object; + GError *error = NULL; + + g_assert (G_IS_PERMISSION (permission)); + g_assert (G_IS_ASYNC_RESULT (result)); + g_assert (G_IS_TASK (task)); + + if (!g_permission_acquire_finish (permission, result, &error)) + { + g_task_return_error (task, error); + return; + } + + g_task_return_boolean (task, TRUE); +} + +static void +sp_perf_counter_permission_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + g_autoptr(GTask) task = user_data; + GPermission *permission; + GError *error = NULL; + + g_assert (G_IS_ASYNC_RESULT (result)); + g_assert (G_IS_TASK (task)); + + if (NULL == (permission = polkit_permission_new_finish (result, &error))) + { + g_task_return_error (task, error); + return; + } + + g_permission_acquire_async (permission, + g_task_get_cancellable (task), + sp_perf_counter_acquire_cb, + g_object_ref (task)); + + g_object_unref (permission); +} + +static void +sp_perf_counter_get_bus_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + g_autoptr(GDBusConnection) bus = NULL; + g_autoptr(GTask) task = user_data; + PolkitSubject *subject = NULL; + const gchar *name; + GError *error = NULL; + + g_assert (G_IS_ASYNC_RESULT (result)); + g_assert (G_IS_TASK (task)); + + if (NULL == (bus = g_bus_get_finish (result, &error))) + { + g_task_return_error (task, error); + return; + } + + shared_conn = g_object_ref (bus); + + name = g_dbus_connection_get_unique_name (bus); + subject = polkit_system_bus_name_new (name); + + polkit_permission_new ("org.gnome.sysprof2.perf-event-open", + subject, + g_task_get_cancellable (task), + sp_perf_counter_permission_cb, + g_object_ref (task)); + + g_object_unref (subject); +} + #endif +void +sp_perf_counter_authorize_async (GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_autoptr(GTask) task = NULL; + + g_assert (!cancellable || G_IS_CANCELLABLE (cancellable)); + + task = g_task_new (NULL, cancellable, callback, user_data); + +#if ENABLE_SYSPROFD + g_bus_get (G_BUS_TYPE_SYSTEM, + cancellable, + sp_perf_counter_get_bus_cb, + g_object_ref (task)); +#else + g_task_return_new_error (error, + G_IO_ERROR, + G_IO_ERROR_NOT_SUPPORTED, + "Sysprofd is not supported in current configuration"); +#endif +} + +gboolean +sp_perf_counter_authorize_finish (GAsyncResult *result, + GError **error) +{ + g_assert (G_IS_TASK (result)); + + return g_task_propagate_boolean (G_TASK (result), error); +} + gint sp_perf_counter_open (SpPerfCounter *self, struct perf_event_attr *attr, diff --git a/lib/sp-perf-counter.h b/lib/sp-perf-counter.h index d90f8b99..2d870ad6 100644 --- a/lib/sp-perf-counter.h +++ b/lib/sp-perf-counter.h @@ -19,7 +19,7 @@ #ifndef SP_PERF_COUNTER_H #define SP_PERF_COUNTER_H -#include +#include #include @@ -110,6 +110,12 @@ typedef void (*SpPerfCounterCallback) (SpPerfCounterEvent *event, guint cpu, gpointer user_data); +void sp_perf_counter_authorize_async (GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean sp_perf_counter_authorize_finish (GAsyncResult *result, + GError **error); + GType sp_perf_counter_get_type (void); SpPerfCounter *sp_perf_counter_new (GMainContext *context); void sp_perf_counter_set_callback (SpPerfCounter *self, diff --git a/lib/sp-perf-source.c b/lib/sp-perf-source.c index 8a4f7540..e5d44559 100644 --- a/lib/sp-perf-source.c +++ b/lib/sp-perf-source.c @@ -55,6 +55,7 @@ struct _SpPerfSource GHashTable *pids; guint running : 1; + guint is_ready : 1; }; static void source_iface_init (SpSourceInterface *iface); @@ -430,6 +431,49 @@ sp_perf_source_add_pid (SpSource *source, g_hash_table_add (self->pids, GINT_TO_POINTER (pid)); } +static void +sp_perf_source_authorize_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + g_autoptr(SpPerfSource) self = user_data; + g_autoptr(GError) error = NULL; + + g_assert (G_IS_ASYNC_RESULT (result)); + + if (!sp_perf_counter_authorize_finish (result, &error)) + { + sp_source_emit_failed (SP_SOURCE (self), error); + return; + } + + self->is_ready = TRUE; + + sp_source_emit_ready (SP_SOURCE (self)); +} + +static void +sp_perf_source_prepare (SpSource *source) +{ + SpPerfSource *self = (SpPerfSource *)source; + + g_assert (SP_IS_PERF_SOURCE (self)); + + sp_perf_counter_authorize_async (NULL, + sp_perf_source_authorize_cb, + g_object_ref (self)); +} + +static gboolean +sp_perf_source_get_is_ready (SpSource *source) +{ + SpPerfSource *self = (SpPerfSource *)source; + + g_assert (SP_IS_PERF_SOURCE (self)); + + return self->is_ready; +} + static void source_iface_init (SpSourceInterface *iface) { @@ -437,6 +481,8 @@ source_iface_init (SpSourceInterface *iface) iface->stop = sp_perf_source_stop; iface->set_writer = sp_perf_source_set_writer; iface->add_pid = sp_perf_source_add_pid; + iface->prepare = sp_perf_source_prepare; + iface->get_is_ready = sp_perf_source_get_is_ready; } SpSource *