mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2025-12-31 20:36:25 +00:00
libsysprof/instruments: use provided D-Bus connection for sysprofd
If we were provided a D-Bus connection to use for sysprofd then use that. Otherwise, try to fallback to doing the work in process without the help of sysprofd.
This commit is contained in:
@ -159,6 +159,8 @@ libsysprof_private_sources = [
|
||||
'sysprof-util.c',
|
||||
'timsort/gtktimsort.c',
|
||||
|
||||
'../sysprofd/helpers.c',
|
||||
|
||||
gnome.gdbus_codegen('ipc-unwinder',
|
||||
sources: '../sysprofd/org.gnome.Sysprof3.Unwinder.xml',
|
||||
interface_prefix: 'org.gnome.Sysprof3.',
|
||||
|
||||
@ -29,11 +29,16 @@
|
||||
|
||||
#include "line-reader-private.h"
|
||||
|
||||
#include "../sysprofd/helpers.h"
|
||||
|
||||
#define PROCESS_INFO_KEYS "pid,maps,mountinfo,cmdline,comm,cgroup"
|
||||
|
||||
struct _SysprofLinuxInstrument
|
||||
{
|
||||
SysprofInstrument parent_instance;
|
||||
SysprofRecording *recording;
|
||||
GHashTable *seen;
|
||||
SysprofInstrument parent_instance;
|
||||
GDBusConnection *connection;
|
||||
SysprofRecording *recording;
|
||||
GHashTable *seen;
|
||||
};
|
||||
|
||||
G_DEFINE_FINAL_TYPE (SysprofLinuxInstrument, sysprof_linux_instrument, SYSPROF_TYPE_INSTRUMENT)
|
||||
@ -46,6 +51,15 @@ sysprof_linux_instrument_list_required_policy (SysprofInstrument *instrument)
|
||||
return g_strdupv ((char **)policy);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_linux_instrument_set_connection (SysprofInstrument *instrument,
|
||||
GDBusConnection *connection)
|
||||
{
|
||||
SysprofLinuxInstrument *self = SYSPROF_LINUX_INSTRUMENT (instrument);
|
||||
|
||||
g_set_object (&self->connection, connection);
|
||||
}
|
||||
|
||||
static void
|
||||
add_mmaps (SysprofRecording *recording,
|
||||
GPid pid,
|
||||
@ -237,11 +251,35 @@ add_process_info (SysprofLinuxInstrument *self,
|
||||
return dex_future_new_for_boolean (TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
get_process_info_task (gpointer data)
|
||||
{
|
||||
g_autoptr(DexPromise) promise = data;
|
||||
g_autoptr(GVariant) info = NULL;
|
||||
|
||||
if (!(info = helpers_get_process_info (PROCESS_INFO_KEYS)))
|
||||
dex_promise_reject (promise,
|
||||
g_error_new (G_IO_ERROR,
|
||||
G_IO_ERROR_PERMISSION_DENIED,
|
||||
"Failed to load process info"));
|
||||
else
|
||||
dex_promise_resolve_variant (promise, g_steal_pointer (&info));
|
||||
}
|
||||
|
||||
static DexFuture *
|
||||
get_process_info (void)
|
||||
{
|
||||
DexPromise *promise = dex_promise_new ();
|
||||
dex_scheduler_push (dex_thread_pool_scheduler_get_default (),
|
||||
get_process_info_task,
|
||||
dex_ref (promise));
|
||||
return DEX_FUTURE (g_steal_pointer (&promise));
|
||||
}
|
||||
|
||||
static DexFuture *
|
||||
sysprof_linux_instrument_prepare_fiber (gpointer user_data)
|
||||
{
|
||||
SysprofLinuxInstrument *self = user_data;
|
||||
g_autoptr(GDBusConnection) bus = NULL;
|
||||
g_autoptr(GVariant) process_info_reply = NULL;
|
||||
g_autoptr(GVariant) process_info = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
@ -259,28 +297,37 @@ sysprof_linux_instrument_prepare_fiber (gpointer user_data)
|
||||
&error))
|
||||
return dex_future_new_for_error (g_steal_pointer (&error));
|
||||
|
||||
/* We need access to the bus to call various sysprofd API directly */
|
||||
if (!(bus = dex_await_object (dex_bus_get (G_BUS_TYPE_SYSTEM), &error)))
|
||||
return dex_future_new_for_error (g_steal_pointer (&error));
|
||||
|
||||
/* We also want to get a bunch of info on user processes so that we can add
|
||||
* records about them to the recording.
|
||||
*/
|
||||
at_time = SYSPROF_CAPTURE_CURRENT_TIME;
|
||||
if (!(process_info_reply = dex_await_variant (dex_dbus_connection_call (bus,
|
||||
"org.gnome.Sysprof3",
|
||||
"/org/gnome/Sysprof3",
|
||||
"org.gnome.Sysprof3.Service",
|
||||
"GetProcessInfo",
|
||||
g_variant_new ("(s)", "pid,maps,mountinfo,cmdline,comm,cgroup"),
|
||||
G_VARIANT_TYPE ("(aa{sv})"),
|
||||
G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION,
|
||||
G_MAXINT),
|
||||
&error)))
|
||||
return dex_future_new_for_error (g_steal_pointer (&error));
|
||||
|
||||
/* Add process records for each of the processes discovered */
|
||||
process_info = g_variant_get_child_value (process_info_reply, 0);
|
||||
if (self->connection != NULL)
|
||||
{
|
||||
/* We also want to get a bunch of info on user processes so that we can add
|
||||
* records about them to the recording.
|
||||
*/
|
||||
if (!(process_info_reply = dex_await_variant (dex_dbus_connection_call (self->connection,
|
||||
"org.gnome.Sysprof3",
|
||||
"/org/gnome/Sysprof3",
|
||||
"org.gnome.Sysprof3.Service",
|
||||
"GetProcessInfo",
|
||||
g_variant_new ("(s)", PROCESS_INFO_KEYS),
|
||||
G_VARIANT_TYPE ("(aa{sv})"),
|
||||
G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION,
|
||||
G_MAXINT),
|
||||
&error)))
|
||||
return dex_future_new_for_error (g_steal_pointer (&error));
|
||||
|
||||
/* Add process records for each of the processes discovered */
|
||||
process_info = g_variant_get_child_value (process_info_reply, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Load process info using same mechanism as sysprofd */
|
||||
if (!(process_info = dex_await_variant (get_process_info (), &error)))
|
||||
return dex_future_new_for_error (g_steal_pointer (&error));
|
||||
}
|
||||
|
||||
g_assert (process_info != NULL);
|
||||
|
||||
dex_await (add_process_info (self, self->recording, process_info, at_time), NULL);
|
||||
|
||||
return dex_future_new_for_boolean (TRUE);
|
||||
@ -454,6 +501,7 @@ sysprof_linux_instrument_dispose (GObject *object)
|
||||
{
|
||||
SysprofLinuxInstrument *self = (SysprofLinuxInstrument *)object;
|
||||
|
||||
g_clear_object (&self->connection);
|
||||
g_clear_object (&self->recording);
|
||||
g_hash_table_remove_all (self->seen);
|
||||
|
||||
@ -482,6 +530,7 @@ sysprof_linux_instrument_class_init (SysprofLinuxInstrumentClass *klass)
|
||||
instrument_class->list_required_policy = sysprof_linux_instrument_list_required_policy;
|
||||
instrument_class->prepare = sysprof_linux_instrument_prepare;
|
||||
instrument_class->process_started = sysprof_linux_instrument_process_started;
|
||||
instrument_class->set_connection = sysprof_linux_instrument_set_connection;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@ -29,10 +29,11 @@
|
||||
|
||||
struct _SysprofSampler
|
||||
{
|
||||
SysprofInstrument parent_instance;
|
||||
GPtrArray *perf_event_streams;
|
||||
guint sample_lost_counter_id;
|
||||
gint64 lost_count;
|
||||
SysprofInstrument parent_instance;
|
||||
GDBusConnection *connection;
|
||||
GPtrArray *perf_event_streams;
|
||||
guint sample_lost_counter_id;
|
||||
gint64 lost_count;
|
||||
};
|
||||
|
||||
struct _SysprofSamplerClass
|
||||
@ -312,7 +313,8 @@ sysprof_sampler_perf_event_stream_cb (const SysprofPerfEvent *event,
|
||||
typedef struct _Prepare
|
||||
{
|
||||
SysprofRecording *recording;
|
||||
SysprofSampler *sampler;
|
||||
SysprofSampler *sampler;
|
||||
GDBusConnection *connection;
|
||||
} Prepare;
|
||||
|
||||
static void
|
||||
@ -320,6 +322,7 @@ prepare_free (Prepare *prepare)
|
||||
{
|
||||
g_clear_object (&prepare->recording);
|
||||
g_clear_object (&prepare->sampler);
|
||||
g_clear_object (&prepare->connection);
|
||||
g_free (prepare);
|
||||
}
|
||||
|
||||
@ -327,7 +330,6 @@ static DexFuture *
|
||||
sysprof_sampler_prepare_fiber (gpointer user_data)
|
||||
{
|
||||
Prepare *prepare = user_data;
|
||||
g_autoptr(GDBusConnection) connection = NULL;
|
||||
g_autoptr(StreamData) stream_data = NULL;
|
||||
g_autoptr(GPtrArray) futures = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
@ -339,6 +341,7 @@ sysprof_sampler_prepare_fiber (gpointer user_data)
|
||||
g_assert (prepare != NULL);
|
||||
g_assert (SYSPROF_IS_RECORDING (prepare->recording));
|
||||
g_assert (SYSPROF_IS_SAMPLER (prepare->sampler));
|
||||
g_assert (!prepare->connection || G_IS_DBUS_CONNECTION (prepare->connection));
|
||||
|
||||
/* First thing we need to do is to ensure the consumer has
|
||||
* access to kallsyms, which may be from a machine, or boot
|
||||
@ -406,16 +409,13 @@ try_again:
|
||||
attr.sample_period = 1200000;
|
||||
}
|
||||
|
||||
if (!(connection = dex_await_object (dex_bus_get (G_BUS_TYPE_SYSTEM), &error)))
|
||||
return dex_future_new_for_error (g_steal_pointer (&error));
|
||||
|
||||
/* Pipeline our request for n_cpu perf_event_open calls and then
|
||||
* await them all to complete.
|
||||
*/
|
||||
stream_data = stream_data_new (prepare->recording);
|
||||
for (guint i = 0; i < n_cpu; i++)
|
||||
g_ptr_array_add (futures,
|
||||
sysprof_perf_event_stream_new (connection,
|
||||
sysprof_perf_event_stream_new (prepare->connection,
|
||||
&attr,
|
||||
i,
|
||||
-1,
|
||||
@ -513,8 +513,9 @@ sysprof_sampler_prepare (SysprofInstrument *instrument,
|
||||
g_assert (SYSPROF_IS_RECORDING (recording));
|
||||
|
||||
prepare = g_new0 (Prepare, 1);
|
||||
prepare->recording = g_object_ref (recording);
|
||||
prepare->sampler = g_object_ref (self);
|
||||
g_set_object (&prepare->recording, recording);
|
||||
g_set_object (&prepare->sampler, self);
|
||||
g_set_object (&prepare->connection, self->connection);
|
||||
|
||||
return dex_scheduler_spawn (NULL, 0,
|
||||
sysprof_sampler_prepare_fiber,
|
||||
@ -590,12 +591,22 @@ sysprof_sampler_record (SysprofInstrument *instrument,
|
||||
(GDestroyNotify)record_free);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_sampler_set_connection (SysprofInstrument *instrument,
|
||||
GDBusConnection *connection)
|
||||
{
|
||||
SysprofSampler *self = SYSPROF_SAMPLER (instrument);
|
||||
|
||||
g_set_object (&self->connection, connection);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_sampler_finalize (GObject *object)
|
||||
{
|
||||
SysprofSampler *self = (SysprofSampler *)object;
|
||||
|
||||
g_clear_pointer (&self->perf_event_streams, g_ptr_array_unref);
|
||||
g_clear_object (&self->connection);
|
||||
|
||||
G_OBJECT_CLASS (sysprof_sampler_parent_class)->finalize (object);
|
||||
}
|
||||
@ -611,6 +622,7 @@ sysprof_sampler_class_init (SysprofSamplerClass *klass)
|
||||
instrument_class->list_required_policy = sysprof_sampler_list_required_policy;
|
||||
instrument_class->prepare = sysprof_sampler_prepare;
|
||||
instrument_class->record = sysprof_sampler_record;
|
||||
instrument_class->set_connection = sysprof_sampler_set_connection;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
#include "sysprof-perf-event-stream-private.h"
|
||||
#include "sysprof-scheduler-details.h"
|
||||
#include "sysprof-recording-private.h"
|
||||
#include "sysprof-util-private.h"
|
||||
|
||||
#include "line-reader-private.h"
|
||||
|
||||
@ -31,6 +32,7 @@ struct _SysprofSchedulerDetails
|
||||
{
|
||||
SysprofInstrument parent_instance;
|
||||
|
||||
GDBusConnection *connection;
|
||||
SysprofRecording *recording;
|
||||
DexFuture *cancellable;
|
||||
GPtrArray *streams;
|
||||
@ -193,9 +195,8 @@ static DexFuture *
|
||||
sysprof_scheduler_details_prepare_fiber (gpointer user_data)
|
||||
{
|
||||
SysprofSchedulerDetails *self = user_data;
|
||||
g_autoptr(GDBusConnection) bus = NULL;
|
||||
g_autoptr(GPtrArray) futures = NULL;
|
||||
g_autoptr(GVariant) format_reply = NULL;
|
||||
g_autoptr(GBytes) format_bytes = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autofree char *format = NULL;
|
||||
int n_cpu;
|
||||
@ -203,22 +204,13 @@ sysprof_scheduler_details_prepare_fiber (gpointer user_data)
|
||||
g_assert (SYSPROF_IS_SCHEDULER_DETAILS (self));
|
||||
g_assert (SYSPROF_IS_RECORDING (self->recording));
|
||||
|
||||
if (!(bus = dex_await_object (dex_bus_get (G_BUS_TYPE_SYSTEM), &error)))
|
||||
if (!(format_bytes = dex_await_boxed (sysprof_get_proc_file_bytes (self->connection,
|
||||
"/sys/kernel/debug/tracing/events/sched/sched_switch/format"),
|
||||
&error)))
|
||||
goto handle_error;
|
||||
|
||||
if (!(format_reply = dex_await_variant (dex_dbus_connection_call (bus,
|
||||
"org.gnome.Sysprof3",
|
||||
"/org/gnome/Sysprof3",
|
||||
"org.gnome.Sysprof3.Service",
|
||||
"GetProcFile",
|
||||
g_variant_new ("(^ay)", "/sys/kernel/debug/tracing/events/sched/sched_switch/format"),
|
||||
G_VARIANT_TYPE ("(ay)"),
|
||||
G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION,
|
||||
G_MAXINT),
|
||||
&error)))
|
||||
goto handle_error;
|
||||
|
||||
g_variant_get (format_reply, "(^ay)", &format);
|
||||
format = g_strndup (g_bytes_get_data (format_bytes, NULL),
|
||||
g_bytes_get_size (format_bytes));
|
||||
|
||||
if (!sysprof_scheduler_details_parse_format (self, format))
|
||||
{
|
||||
@ -255,7 +247,7 @@ sysprof_scheduler_details_prepare_fiber (gpointer user_data)
|
||||
attr.size = sizeof attr;
|
||||
|
||||
g_ptr_array_add (futures,
|
||||
sysprof_perf_event_stream_new (bus,
|
||||
sysprof_perf_event_stream_new (self->connection,
|
||||
&attr,
|
||||
cpu,
|
||||
-1,
|
||||
@ -361,6 +353,15 @@ sysprof_scheduler_details_record (SysprofInstrument *instrument,
|
||||
g_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_scheduler_details_set_connection (SysprofInstrument *instrument,
|
||||
GDBusConnection *connection)
|
||||
{
|
||||
SysprofSchedulerDetails *self = SYSPROF_SCHEDULER_DETAILS (instrument);
|
||||
|
||||
g_set_object (&self->connection, connection);
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof_scheduler_details_dispose (GObject *object)
|
||||
{
|
||||
@ -377,6 +378,7 @@ sysprof_scheduler_details_dispose (GObject *object)
|
||||
g_clear_pointer (&self->streams, g_ptr_array_unref);
|
||||
}
|
||||
|
||||
g_clear_object (&self->connection);
|
||||
g_clear_object (&self->recording);
|
||||
g_clear_pointer (&self->last_switch_times, g_free);
|
||||
dex_clear (&self->cancellable);
|
||||
@ -394,6 +396,7 @@ sysprof_scheduler_details_class_init (SysprofSchedulerDetailsClass *klass)
|
||||
|
||||
instrument_class->prepare = sysprof_scheduler_details_prepare;
|
||||
instrument_class->record = sysprof_scheduler_details_record;
|
||||
instrument_class->set_connection = sysprof_scheduler_details_set_connection;
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
Reference in New Issue
Block a user