[sysprof] src: use helpers and add group_fd to remote API
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [sysprof] src: use helpers and add group_fd to remote API
- Date: Wed, 29 May 2019 22:17:32 +0000 (UTC)
commit cd3b4d653822173937b78d7c2f5248e1e2f9fed0
Author: Christian Hergert <chergert redhat com>
Date: Thu May 9 12:31:08 2019 -0700
src: use helpers and add group_fd to remote API
src/libsysprof/meson.build | 10 +-
src/libsysprof/sysprof-helpers.c | 353 +++++++++++++++++++++++++++++++++++++
src/libsysprof/sysprof-helpers.h | 70 ++++++++
src/meson.build | 12 ++
src/org.gnome.Sysprof3.Service.xml | 2 +
src/sysprofd/ipc-service-impl.c | 289 ++++++------------------------
src/sysprofd/meson.build | 8 +-
7 files changed, 504 insertions(+), 240 deletions(-)
---
diff --git a/src/libsysprof/meson.build b/src/libsysprof/meson.build
index 740f89c..cf6e51a 100644
--- a/src/libsysprof/meson.build
+++ b/src/libsysprof/meson.build
@@ -44,11 +44,15 @@ libsysprof_public_headers = [
]
libsysprof_private_sources = [
- '../stackstash.c',
'binfile.c',
'demangle.cpp',
'elfparser.c',
+ 'ipc-service-client.c',
+ 'sysprof-helpers.c',
'sysprof-line-reader.c',
+ ipc_service_src,
+ stackstash_sources,
+ helpers_sources,
]
libsysprof_public_sources += libsysprof_capture_sources
@@ -94,7 +98,9 @@ libsysprof = shared_library(
'sysprof-@0@'.format(libsysprof_api_version),
libsysprof_public_sources + libsysprof_private_sources,
- include_directories: [include_directories('.'), libsysprof_capture_include_dirs],
+ include_directories: [include_directories('.'),
+ ipc_include_dirs,
+ libsysprof_capture_include_dirs],
dependencies: libsysprof_deps,
c_args: libsysprof_c_args,
install: true,
diff --git a/src/libsysprof/sysprof-helpers.c b/src/libsysprof/sysprof-helpers.c
new file mode 100644
index 0000000..2966f08
--- /dev/null
+++ b/src/libsysprof/sysprof-helpers.c
@@ -0,0 +1,353 @@
+/* sysprof-helpers.c
+ *
+ * Copyright 2019 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "sysprof-helpers"
+
+#include "config.h"
+
+#include <gio/gunixfdlist.h>
+
+#include "sysprof-helpers.h"
+
+#include "helpers.h"
+#include "ipc-service.h"
+
+struct _SysprofHelpers
+{
+ GObject parent_instance;
+ IpcService *proxy;
+};
+
+G_DEFINE_TYPE (SysprofHelpers, sysprof_helpers, G_TYPE_OBJECT)
+
+static void
+sysprof_helpers_finalize (GObject *object)
+{
+ SysprofHelpers *self = (SysprofHelpers *)object;
+
+ g_clear_object (&self->proxy);
+
+ G_OBJECT_CLASS (sysprof_helpers_parent_class)->finalize (object);
+}
+
+static void
+sysprof_helpers_class_init (SysprofHelpersClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = sysprof_helpers_finalize;
+}
+
+static void
+sysprof_helpers_init (SysprofHelpers *self)
+{
+ g_autoptr(GDBusConnection) bus = NULL;
+
+ bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
+ g_return_if_fail (bus != NULL);
+
+ self->proxy = ipc_service_proxy_new_sync (bus,
+ G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START_AT_CONSTRUCTION,
+ "org.gnome.Sysprof3",
+ "/org/gnome/Sysprof3",
+ NULL, NULL);
+ g_return_if_fail (self->proxy != NULL);
+}
+
+SysprofHelpers *
+sysprof_helpers_get_default (void)
+{
+ static SysprofHelpers *instance;
+
+ if (g_once_init_enter (&instance))
+ {
+ SysprofHelpers *self = g_object_new (SYSPROF_TYPE_HELPERS, NULL);
+ g_object_add_weak_pointer (G_OBJECT (instance), (gpointer *)&instance);
+ g_once_init_leave (&instance, self);
+ }
+
+ return instance;
+}
+
+static gboolean
+fail_if_no_proxy (SysprofHelpers *self,
+ GTask *task)
+{
+ g_assert (SYSPROF_IS_HELPERS (self));
+ g_assert (G_IS_TASK (task));
+
+ if (self->proxy == NULL)
+ {
+ g_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_CONNECTED,
+ "No D-Bus proxy to communicate with daemon");
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+sysprof_helpers_list_processes_cb (IpcService *service,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = user_data;
+ g_autoptr(GVariant) processes = NULL;
+ g_autoptr(GError) error = NULL;
+
+ g_assert (IPC_IS_SERVICE (service));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (G_IS_TASK (task));
+
+ if (!ipc_service_call_list_processes_finish (service, &processes, result, &error))
+ {
+ g_autofree gint32 *out_processes = NULL;
+ gsize out_n_processes = 0;
+
+ if (helpers_list_processes (&out_processes, &out_n_processes))
+ processes = g_variant_new_fixed_array (G_VARIANT_TYPE_INT32,
+ out_processes,
+ out_n_processes,
+ sizeof (gint32));
+ }
+
+ if (processes != NULL)
+ g_task_return_pointer (task, g_steal_pointer (&processes), (GDestroyNotify) g_variant_unref);
+ else
+ g_task_return_new_error (task,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_SUPPORTED,
+ "Failed to list processes");
+}
+
+void
+sysprof_helpers_list_processes_async (SysprofHelpers *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (SYSPROF_IS_HELPERS (self));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_source_tag (task, sysprof_helpers_list_processes_async);
+
+ if (!fail_if_no_proxy (self, task))
+ ipc_service_call_list_processes (self->proxy,
+ cancellable,
+ (GAsyncReadyCallback) sysprof_helpers_list_processes_cb,
+ g_steal_pointer (&task));
+}
+
+gboolean
+sysprof_helpers_list_processes_finish (SysprofHelpers *self,
+ GAsyncResult *result,
+ gint32 **processes,
+ gsize *n_processes,
+ GError **error)
+{
+ g_autoptr(GVariant) ret = NULL;
+
+ g_return_val_if_fail (SYSPROF_IS_HELPERS (self), FALSE);
+ g_return_val_if_fail (G_IS_TASK (result), FALSE);
+
+ if ((ret = g_task_propagate_pointer (G_TASK (result), error)))
+ {
+ const gint32 *p;
+ gsize n;
+
+ p = g_variant_get_fixed_array (ret, &n, sizeof (gint32));
+
+ if (processes != NULL)
+ *processes = g_memdup (p, n * sizeof (gint32));
+
+ if (n_processes != NULL)
+ *n_processes = n;
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+#ifdef __linux__
+static void
+sysprof_helpers_get_proc_file_cb (IpcService *service,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = user_data;
+ g_autoptr(GError) error = NULL;
+ g_autofree gchar *contents = NULL;
+
+ g_assert (IPC_IS_SERVICE (service));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (G_IS_TASK (task));
+
+ if (!ipc_service_call_get_proc_file_finish (service, &contents, result, &error))
+ g_task_return_error (task, g_steal_pointer (&error));
+ else
+ g_task_return_pointer (task, g_steal_pointer (&contents), g_free);
+}
+
+void
+sysprof_helpers_get_proc_file_async (SysprofHelpers *self,
+ const gchar *path,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+
+ g_return_if_fail (SYSPROF_IS_HELPERS (self));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_source_tag (task, sysprof_helpers_list_processes_async);
+
+ if (!fail_if_no_proxy (self, task))
+ ipc_service_call_get_proc_file (self->proxy,
+ path,
+ cancellable,
+ (GAsyncReadyCallback) sysprof_helpers_get_proc_file_cb,
+ g_steal_pointer (&task));
+}
+
+gboolean
+sysprof_helpers_get_proc_file_finish (SysprofHelpers *self,
+ GAsyncResult *result,
+ gchar **contents,
+ GError **error)
+{
+ g_autofree gchar *ret = NULL;
+
+ g_return_val_if_fail (SYSPROF_IS_HELPERS (self), FALSE);
+ g_return_val_if_fail (G_IS_TASK (result), FALSE);
+
+ if ((ret = g_task_propagate_pointer (G_TASK (result), error)))
+ {
+ if (contents != NULL)
+ *contents = g_steal_pointer (&ret);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+sysprof_helpers_perf_event_open_cb (IpcService *service,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = user_data;
+ g_autoptr(GUnixFDList) fd_list = NULL;
+ g_autoptr(GError) error = NULL;
+
+ g_assert (IPC_IS_SERVICE (service));
+ g_assert (G_IS_ASYNC_RESULT (result));
+ g_assert (G_IS_TASK (task));
+
+ if (!g_dbus_proxy_call_with_unix_fd_list_finish (G_DBUS_PROXY (service),
+ &fd_list,
+ result,
+ &error))
+ g_task_return_error (task, g_steal_pointer (&error));
+ else
+ g_task_return_pointer (task, g_steal_pointer (&fd_list), g_object_unref);
+}
+
+void
+sysprof_helpers_perf_event_open_async (SysprofHelpers *self,
+ struct perf_event_attr *attr,
+ gint32 pid,
+ gint32 cpu,
+ gint32 group_fd,
+ guint64 flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+ g_autoptr(GVariant) options = NULL;
+
+ g_return_if_fail (SYSPROF_IS_HELPERS (self));
+ g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = g_task_new (self, cancellable, callback, user_data);
+ g_task_set_source_tag (task, sysprof_helpers_list_processes_async);
+
+ if (!fail_if_no_proxy (self, task))
+ g_dbus_proxy_call_with_unix_fd_list (G_DBUS_PROXY (self->proxy),
+ "PerfEventOpen",
+ g_variant_new ("(@a{sv}iit)",
+ options,
+ pid,
+ cpu,
+ flags),
+ G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION,
+ -1,
+ NULL,
+ cancellable,
+ (GAsyncReadyCallback) sysprof_helpers_perf_event_open_cb,
+ g_steal_pointer (&task));
+}
+
+gboolean
+sysprof_helpers_perf_event_open_finish (SysprofHelpers *self,
+ GAsyncResult *result,
+ gint *out_fd,
+ GError **error)
+{
+ g_autoptr(GUnixFDList) fd_list = NULL;
+
+ g_return_val_if_fail (SYSPROF_IS_HELPERS (self), FALSE);
+ g_return_val_if_fail (G_IS_TASK (result), FALSE);
+
+ if ((fd_list = g_task_propagate_pointer (G_TASK (result), error)))
+ {
+ if (g_unix_fd_list_get_length (fd_list) != 1)
+ {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_FAILED,
+ "Incorrect number of FDs from peer");
+ return FALSE;
+ }
+
+ if (out_fd != NULL)
+ {
+ gint fd = g_unix_fd_list_get (fd_list, 0, error);
+
+ if (fd == -1)
+ return FALSE;
+
+ *out_fd = fd;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+#endif /* __linux__ */
diff --git a/src/libsysprof/sysprof-helpers.h b/src/libsysprof/sysprof-helpers.h
new file mode 100644
index 0000000..962549f
--- /dev/null
+++ b/src/libsysprof/sysprof-helpers.h
@@ -0,0 +1,70 @@
+/* sysprof-helpers.h
+ *
+ * Copyright 2019 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <gio/gio.h>
+
+#ifdef __linux__
+# include <linux/perf_event.h>
+#endif
+
+G_BEGIN_DECLS
+
+#define SYSPROF_TYPE_HELPERS (sysprof_helpers_get_type())
+
+G_DECLARE_FINAL_TYPE (SysprofHelpers, sysprof_helpers, SYSPROF, HELPERS, GObject)
+
+SysprofHelpers *sysprof_helpers_get_default (void);
+void sysprof_helpers_list_processes_async (SysprofHelpers *self,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean sysprof_helpers_list_processes_finish (SysprofHelpers *self,
+ GAsyncResult *result,
+ gint32 **processes,
+ gsize *n_processes,
+ GError **error);
+#ifdef __linux__
+void sysprof_helpers_get_proc_file_async (SysprofHelpers *self,
+ const gchar *path,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean sysprof_helpers_get_proc_file_finish (SysprofHelpers *self,
+ GAsyncResult *result,
+ gchar **contents,
+ GError **error);
+void sysprof_helpers_perf_event_open_async (SysprofHelpers *self,
+ struct perf_event_attr *attr,
+ gint32 pid,
+ gint32 cpu,
+ gint32 group_fd,
+ guint64 flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean sysprof_helpers_perf_event_open_finish (SysprofHelpers *self,
+ GAsyncResult *result,
+ gint *out_fd,
+ GError **error);
+#endif
+
+G_END_DECLS
diff --git a/src/meson.build b/src/meson.build
index 6210306..f0db4b7 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -7,6 +7,18 @@ sysprof_version_conf.set('MINOR_VERSION', sysprof_version[1])
sysprof_version_conf.set('MICRO_VERSION', sysprof_version[2])
sysprof_version_conf.set('VERSION', meson.project_version())
+ipc_service_src = gnome.gdbus_codegen('ipc-service',
+ sources: 'org.gnome.Sysprof3.Service.xml',
+ interface_prefix: 'org.gnome.Sysprof3.',
+ namespace: 'Ipc',
+)
+
+ipc_include_dirs = include_directories('.')
+
+stackstash_sources = files([
+ 'stackstash.c',
+])
+
helpers_sources = files([
'helpers.c',
])
diff --git a/src/org.gnome.Sysprof3.Service.xml b/src/org.gnome.Sysprof3.Service.xml
index 0f6d6b4..c4b4a86 100644
--- a/src/org.gnome.Sysprof3.Service.xml
+++ b/src/org.gnome.Sysprof3.Service.xml
@@ -7,6 +7,7 @@
@options: key-value pair of attributes for the perf_event_open() syscall.
@pid: the process id to monitor, or -1 for system-wide.
@cpu: affinity to cpu.
+ @group: a FD handle for an existing group
@flags: flags for perf_event_open() syscall.
@perf_stream_fd: (out): A fd to communicate with perf.
@@ -17,6 +18,7 @@
<arg name="options" type="a{sv}" direction="in"/>
<arg name="pid" type="i" direction="in"/>
<arg name="cpu" type="i" direction="in"/>
+ <arg name="group_fd" type="h" direction="in"/>
<arg name="flags" type="t" direction="in"/>
<arg name="perf_stream_fd" type="h" direction="out"/>
</method>
diff --git a/src/sysprofd/ipc-service-impl.c b/src/sysprofd/ipc-service-impl.c
index 8c5263a..60aec07 100644
--- a/src/sysprofd/ipc-service-impl.c
+++ b/src/sysprofd/ipc-service-impl.c
@@ -24,15 +24,12 @@
#include <errno.h>
#include <gio/gunixfdlist.h>
-#ifdef __linux__
-# include <linux/capability.h>
-# include <linux/perf_event.h>
-#endif
#include <polkit/polkit.h>
#include <sys/syscall.h>
#include <time.h>
#include <unistd.h>
+#include "helpers.h"
#include "ipc-service-impl.h"
struct _IpcServiceImpl
@@ -44,47 +41,26 @@ static gboolean
ipc_service_impl_handle_list_processes (IpcService *service,
GDBusMethodInvocation *invocation)
{
- g_autoptr(GDir) dir = NULL;
- g_autoptr(GArray) pids = NULL;
- const gchar *name;
+ g_autofree gint32 *processes = NULL;
+ gsize n_processes = 0;
g_assert (IPC_IS_SERVICE_IMPL (service));
g_assert (G_IS_DBUS_METHOD_INVOCATION (invocation));
g_message ("ListProcesses()");
- if (!(dir = g_dir_open ("/proc/", 0, NULL)))
- {
- g_dbus_method_invocation_return_error (g_steal_pointer (&invocation),
- G_DBUS_ERROR,
- G_DBUS_ERROR_FILE_NOT_FOUND,
- "Failed to access /proc");
- return TRUE;
- }
-
- pids = g_array_new (FALSE, FALSE, sizeof (gint32));
-
- while ((name = g_dir_read_name (dir)))
- {
- if (g_ascii_isalnum (*name))
- {
- gchar *endptr = NULL;
- gint64 val = g_ascii_strtoll (name, &endptr, 10);
-
- if (endptr != NULL && *endptr == 0 && val < G_MAXINT && val >= 0)
- {
- gint32 v32 = val;
- g_array_append_val (pids, v32);
- }
- }
- }
-
- ipc_service_complete_list_processes (service,
- g_steal_pointer (&invocation),
- g_variant_new_fixed_array (G_VARIANT_TYPE_INT32,
- pids->data,
- pids->len,
- sizeof (gint32)));
+ if (!helpers_list_processes (&processes, &n_processes))
+ g_dbus_method_invocation_return_error (g_steal_pointer (&invocation),
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_NOT_SUPPORTED,
+ "Failed to access processes");
+ else
+ ipc_service_complete_list_processes (service,
+ g_steal_pointer (&invocation),
+ g_variant_new_fixed_array (G_VARIANT_TYPE_INT32,
+ processes,
+ n_processes,
+ sizeof (gint32)));
return TRUE;
}
@@ -94,7 +70,6 @@ ipc_service_impl_handle_get_proc_file (IpcService *service,
GDBusMethodInvocation *invocation,
const gchar *path)
{
- g_autofree gchar *canon = NULL;
g_autofree gchar *contents = NULL;
gsize len;
@@ -103,18 +78,11 @@ ipc_service_impl_handle_get_proc_file (IpcService *service,
g_message ("GetProcFile(%s)", path);
- canon = g_canonicalize_filename (path, "/proc/");
-
- if (!g_str_has_prefix (canon, "/proc/"))
+ if (!helpers_get_proc_file (path, &contents, &len))
g_dbus_method_invocation_return_error (g_steal_pointer (&invocation),
G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
- "File is not within /proc/");
- else if (!g_file_get_contents (canon, &contents, &len, NULL))
- g_dbus_method_invocation_return_error (g_steal_pointer (&invocation),
- G_DBUS_ERROR,
- G_DBUS_ERROR_FILE_NOT_FOUND,
- "Failed to locate the file");
+ "Failed to load proc file");
else
ipc_service_complete_get_proc_file (service,
g_steal_pointer (&invocation),
@@ -123,222 +91,79 @@ ipc_service_impl_handle_get_proc_file (IpcService *service,
return TRUE;
}
-#ifdef __linux__
-static int
-_perf_event_open (struct perf_event_attr *attr,
- pid_t pid,
- int cpu,
- int group_fd,
- unsigned long flags)
-{
- g_assert (attr != NULL);
-
- /* Quick sanity check */
- if (attr->sample_period < 100000 && attr->type != PERF_TYPE_TRACEPOINT)
- return -EINVAL;
-
- return syscall (__NR_perf_event_open, attr, pid, cpu, group_fd, flags);
-}
-
static gboolean
ipc_service_impl_handle_perf_event_open (IpcService *service,
GDBusMethodInvocation *invocation,
GVariant *options,
- gint pid,
- gint cpu,
+ gint32 pid,
+ gint32 cpu,
+ GVariant *group_fdv,
guint64 flags)
{
- g_autoptr(GUnixFDList) fd_list = NULL;
- struct perf_event_attr attr = {0};
- GVariantIter iter;
- GVariant *value;
- gchar *key;
- gint32 disabled = 0;
- gint32 wakeup_events = 149;
- gint32 type = 0;
- guint64 sample_period = 0;
- guint64 sample_type = 0;
- guint64 config = 0;
- gint clockid = CLOCK_MONOTONIC;
- gint comm = 0;
- gint mmap_ = 0;
- gint task = 0;
- gint exclude_idle = 0;
- gint fd = -1;
+ GUnixFDList *in_fd_list = NULL;
+ GDBusMessage *message;
+ gint group_fd = -1;
+ gint out_fd = -1;
gint handle;
- gint use_clockid = 0;
- gint sample_id_all = 0;
g_assert (IPC_IS_SERVICE_IMPL (service));
g_assert (G_IS_DBUS_METHOD_INVOCATION (invocation));
g_message ("PerfEventOpen(pid=%d, cpu=%d)", pid, cpu);
- if (pid < -1 || cpu < -1)
+ /* Consistency check for cpu/pid */
+ if (pid < -1 || cpu < -1 || !(pid == -1 && cpu == -1))
{
g_dbus_method_invocation_return_error (g_steal_pointer (&invocation),
G_DBUS_ERROR,
G_DBUS_ERROR_INVALID_ARGS,
- "pid and cpu must be >= -1");
- return TRUE;
- }
-
- g_variant_iter_init (&iter, options);
-
- while (g_variant_iter_loop (&iter, "{sv}", &key, &value))
- {
- if (FALSE) {}
- else if (strcmp (key, "disabled") == 0)
- {
- if (!g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN))
- goto bad_arg;
- disabled = g_variant_get_boolean (value);
- }
- else if (strcmp (key, "wakeup_events") == 0)
- {
- if (!g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32))
- goto bad_arg;
- wakeup_events = g_variant_get_uint32 (value);
- }
- else if (strcmp (key, "sample_id_all") == 0)
- {
- if (!g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN))
- goto bad_arg;
- sample_id_all = g_variant_get_boolean (value);
- }
- else if (strcmp (key, "clockid") == 0)
- {
- if (!g_variant_is_of_type (value, G_VARIANT_TYPE_INT32))
- goto bad_arg;
- clockid = g_variant_get_int32 (value);
- }
- else if (strcmp (key, "comm") == 0)
- {
- if (!g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN))
- goto bad_arg;
- comm = g_variant_get_boolean (value);
- }
- else if (strcmp (key, "exclude_idle") == 0)
- {
- if (!g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN))
- goto bad_arg;
- exclude_idle = g_variant_get_boolean (value);
- }
- else if (strcmp (key, "mmap") == 0)
- {
- if (!g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN))
- goto bad_arg;
- mmap_ = g_variant_get_boolean (value);
- }
- else if (strcmp (key, "config") == 0)
- {
- if (!g_variant_is_of_type (value, G_VARIANT_TYPE_UINT64))
- goto bad_arg;
- config = g_variant_get_uint64 (value);
- }
- else if (strcmp (key, "sample_period") == 0)
- {
- if (!g_variant_is_of_type (value, G_VARIANT_TYPE_UINT64))
- goto bad_arg;
- sample_period = g_variant_get_uint64 (value);
- }
- else if (strcmp (key, "sample_type") == 0)
- {
- if (!g_variant_is_of_type (value, G_VARIANT_TYPE_UINT64))
- goto bad_arg;
- sample_type = g_variant_get_uint64 (value);
- }
- else if (strcmp (key, "task") == 0)
- {
- if (!g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN))
- goto bad_arg;
- task = g_variant_get_boolean (value);
- }
- else if (strcmp (key, "type") == 0)
- {
- if (!g_variant_is_of_type (value, G_VARIANT_TYPE_UINT32))
- goto bad_arg;
- type = g_variant_get_uint32 (value);
- }
- else if (strcmp (key, "use_clockid") == 0)
- {
- if (!g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN))
- goto bad_arg;
- use_clockid = g_variant_get_boolean (value);
- }
-
- continue;
-
- bad_arg:
- g_dbus_method_invocation_return_error (g_steal_pointer (&invocation),
- G_DBUS_ERROR,
- G_DBUS_ERROR_INVALID_ARGS,
- "Invalid type %s for option %s",
- g_variant_get_type_string (value),
- key);
- g_clear_pointer (&value, g_variant_unref);
- g_clear_pointer (&key, g_free);
+ "pid and cpu must be >= -1 and only one may be -1");
return TRUE;
}
- attr.comm = !!comm;
- attr.config = config;
- attr.disabled = disabled;
- attr.exclude_idle = !!exclude_idle;
- attr.mmap = !!mmap_;
- attr.sample_id_all = sample_id_all;
- attr.sample_period = sample_period;
- attr.sample_type = sample_type;
- attr.task = !!task;
- attr.type = type;
- attr.wakeup_events = wakeup_events;
-
-#ifdef HAVE_PERF_CLOCKID
- if (!use_clockid || clockid < 0)
- attr.clockid = CLOCK_MONOTONIC_RAW;
- else
- attr.clockid = clockid;
- attr.use_clockid = use_clockid;
-#endif
-
- attr.size = sizeof attr;
+ /* Get the group_fd if provided */
+ message = g_dbus_method_invocation_get_message (invocation);
+ if ((in_fd_list = g_dbus_message_get_unix_fd_list (message)) &&
+ (handle = g_variant_get_handle (group_fdv)) > -1)
+ group_fd = g_unix_fd_list_get (in_fd_list, handle, NULL);
errno = 0;
- fd = _perf_event_open (&attr, pid, cpu, -1, 0);
-
- if (fd < 0)
+ if (!helpers_perf_event_open (options, pid, cpu, group_fd, flags, &out_fd))
{
g_dbus_method_invocation_return_error (g_steal_pointer (&invocation),
G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
- "Failed to open perf event stream: %s",
+ "Failed to create perf counter: %s",
g_strerror (errno));
- return TRUE;
}
-
- fd_list = g_unix_fd_list_new ();
- handle = g_unix_fd_list_append (fd_list, fd, NULL);
-
- if (handle < 0)
+ else
{
- g_dbus_method_invocation_return_error (g_steal_pointer (&invocation),
- G_DBUS_ERROR,
- G_DBUS_ERROR_FAILED,
- "Failed to send Unix FD List");
- goto close_fd;
+ g_autoptr(GUnixFDList) out_fd_list = g_unix_fd_list_new ();
+ g_autoptr(GError) error = NULL;
+
+ if (-1 == (handle = g_unix_fd_list_append (out_fd_list, out_fd, &error)))
+ {
+ g_dbus_method_invocation_return_error (g_steal_pointer (&invocation),
+ G_DBUS_ERROR,
+ G_DBUS_ERROR_LIMITS_EXCEEDED,
+ "Failed to create file-descriptor for reply");
+ }
+ else
+ {
+ g_dbus_method_invocation_return_value_with_unix_fd_list (g_steal_pointer (&invocation),
+ g_variant_new ("(h)", handle),
+ out_fd_list);
+ }
}
- g_dbus_method_invocation_return_value_with_unix_fd_list (g_steal_pointer (&invocation),
- g_variant_new_handle (handle),
- fd_list);
+ if (out_fd != -1)
+ close (out_fd);
-close_fd:
- if (fd != -1)
- close (fd);
+ if (group_fd != -1)
+ close (group_fd);
return TRUE;
}
-#endif
static gboolean
ipc_service_impl_g_authorize_method (GDBusInterfaceSkeleton *skeleton,
@@ -352,6 +177,8 @@ ipc_service_impl_g_authorize_method (GDBusInterfaceSkeleton *skeleton,
g_assert (IPC_IS_SERVICE_IMPL (skeleton));
g_assert (G_IS_DBUS_METHOD_INVOCATION (invocation));
+ return TRUE;
+
peer_name = g_dbus_method_invocation_get_sender (invocation);
if (!(authority = polkit_authority_get_sync (NULL, NULL)) ||
@@ -382,9 +209,7 @@ init_service_iface (IpcServiceIface *iface)
{
iface->handle_list_processes = ipc_service_impl_handle_list_processes;
iface->handle_get_proc_file = ipc_service_impl_handle_get_proc_file;
-#ifdef __linux__
iface->handle_perf_event_open = ipc_service_impl_handle_perf_event_open;
-#endif
}
G_DEFINE_TYPE_WITH_CODE (IpcServiceImpl, ipc_service_impl, IPC_TYPE_SERVICE_SKELETON,
diff --git a/src/sysprofd/meson.build b/src/sysprofd/meson.build
index fc9b344..4fb195f 100644
--- a/src/sysprofd/meson.build
+++ b/src/sysprofd/meson.build
@@ -1,14 +1,9 @@
if get_option('with_sysprofd') == 'bundled'
-ipc_service_src = gnome.gdbus_codegen('ipc-service',
- sources: 'org.gnome.Sysprof3.Service.xml',
- interface_prefix: 'org.gnome.Sysprof3.',
- namespace: 'Ipc',
-)
-
sysprofd_sources = [
'sysprofd.c',
'ipc-service-impl.c',
+ helpers_sources,
ipc_service_src,
]
@@ -27,6 +22,7 @@ sysprofd = executable('sysprofd', sysprofd_sources,
install: true,
install_dir: pkglibexecdir,
pie: true,
+ include_directories: [include_directories('.'), ipc_include_dirs],
)
sysprofdconf = configuration_data()
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]