mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2025-12-31 20:36:25 +00:00
build: drop legacy v2 service and simplify build system
This removes -Dagent and just uses -Dtools as it only affects sysprof-cli and sysprof-agent. We still need to patch sysprof-cli for recent changes as we did for sysprof-agent though. Additionally, we haven't used the v2 service in forever, so drop that as I can't imagine anyone has been using it.
This commit is contained in:
@ -108,7 +108,6 @@ libsysprof_analyze_static = static_library(
|
||||
libsysprof_analyze_private_sources,
|
||||
|
||||
include_directories: [include_directories('.'),
|
||||
ipc_include_dirs,
|
||||
libsysprof_capture_include_dirs],
|
||||
dependencies: libsysprof_analyze_deps,
|
||||
gnu_symbol_visibility: 'hidden',
|
||||
|
||||
@ -77,7 +77,6 @@ libsysprof_profile_static = static_library(
|
||||
mapped_ring_buffer_sources),
|
||||
|
||||
include_directories: [include_directories('.'),
|
||||
ipc_include_dirs,
|
||||
libsysprof_capture_include_dirs],
|
||||
dependencies: libsysprof_profile_deps,
|
||||
gnu_symbol_visibility: 'hidden',
|
||||
|
||||
@ -15,18 +15,11 @@ if install_service_files
|
||||
'org.gnome.Sysprof2.xml',
|
||||
'org.gnome.Sysprof3.Profiler.xml',
|
||||
'org.gnome.Sysprof3.Service.xml',
|
||||
'org.gnome.Sysprof.Agent.xml'
|
||||
],
|
||||
install_dir: join_paths(datadir, 'dbus-1/interfaces'),
|
||||
)
|
||||
endif
|
||||
|
||||
ipc_include_dirs = include_directories('.')
|
||||
|
||||
stackstash_sources = files('stackstash.c')
|
||||
|
||||
helpers_sources = files('helpers.c')
|
||||
|
||||
if need_libsysprof_capture
|
||||
subdir('libsysprof-capture')
|
||||
endif
|
||||
@ -43,9 +36,12 @@ endif
|
||||
if get_option('sysprofd') == 'bundled'
|
||||
subdir('sysprofd')
|
||||
endif
|
||||
|
||||
if get_option('gtk')
|
||||
subdir('sysprof')
|
||||
endif
|
||||
if get_option('agent')
|
||||
|
||||
if get_option('tools')
|
||||
subdir('sysprof-agent')
|
||||
subdir('sysprof-cli')
|
||||
endif
|
||||
|
||||
@ -23,3 +23,7 @@ sysprof_agent = executable('sysprof-agent', sysprof_agent_sources,
|
||||
install_dir: get_option('bindir'),
|
||||
install: true,
|
||||
)
|
||||
|
||||
install_data(['org.gnome.Sysprof.Agent.xml'],
|
||||
install_dir: join_paths(datadir, 'dbus-1/interfaces'),
|
||||
)
|
||||
|
||||
0
src/sysprof-cli/meson.build
Normal file
0
src/sysprof-cli/meson.build
Normal file
@ -1,218 +0,0 @@
|
||||
/* ipc-legacy-impl.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 "ipc-legacy-impl"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <gio/gunixfdlist.h>
|
||||
#include <polkit/polkit.h>
|
||||
#include <string.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../libsysprof/sysprof-kallsyms.h"
|
||||
#include "helpers.h"
|
||||
#include "ipc-legacy-impl.h"
|
||||
|
||||
struct _IpcLegacyImpl
|
||||
{
|
||||
IpcLegacySysprof2Skeleton parent;
|
||||
};
|
||||
|
||||
enum {
|
||||
ACTIVITY,
|
||||
N_SIGNALS
|
||||
};
|
||||
|
||||
static guint signals [N_SIGNALS];
|
||||
|
||||
static gboolean
|
||||
ipc_legacy_impl_handle_perf_event_open (IpcLegacySysprof2 *service,
|
||||
GDBusMethodInvocation *invocation,
|
||||
GUnixFDList *fd_list,
|
||||
GVariant *options,
|
||||
gint32 pid,
|
||||
gint32 cpu,
|
||||
guint64 flags)
|
||||
{
|
||||
gint out_fd = -1;
|
||||
gint handle;
|
||||
|
||||
g_assert (IPC_IS_LEGACY_IMPL (service));
|
||||
g_assert (G_IS_DBUS_METHOD_INVOCATION (invocation));
|
||||
|
||||
g_message ("LEGACY: PerfEventOpen(pid=%d, cpu=%d)", pid, cpu);
|
||||
|
||||
errno = 0;
|
||||
if (!helpers_perf_event_open (options, pid, cpu, -1, flags, &out_fd))
|
||||
{
|
||||
g_dbus_method_invocation_return_error (g_steal_pointer (&invocation),
|
||||
G_DBUS_ERROR,
|
||||
G_DBUS_ERROR_FAILED,
|
||||
"Failed to create perf counter: %s",
|
||||
g_strerror (errno));
|
||||
}
|
||||
else
|
||||
{
|
||||
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
|
||||
{
|
||||
ipc_legacy_sysprof2_complete_perf_event_open (service,
|
||||
g_steal_pointer (&invocation),
|
||||
out_fd_list,
|
||||
g_variant_new ("h", handle));
|
||||
}
|
||||
}
|
||||
|
||||
if (out_fd != -1)
|
||||
close (out_fd);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ipc_legacy_impl_handle_get_kernal_symbols (IpcLegacySysprof2 *service,
|
||||
GDBusMethodInvocation *invocation)
|
||||
{
|
||||
g_autoptr(SysprofKallsyms) kallsyms = NULL;
|
||||
GVariantBuilder builder;
|
||||
const gchar *name;
|
||||
guint64 addr;
|
||||
guint8 type;
|
||||
|
||||
g_assert (IPC_IS_LEGACY_IMPL (service));
|
||||
g_assert (G_IS_DBUS_METHOD_INVOCATION (invocation));
|
||||
|
||||
g_message ("LEGACY: GetKernelSymbols()");
|
||||
|
||||
if (!(kallsyms = sysprof_kallsyms_new ("/proc/kallsyms")))
|
||||
{
|
||||
g_dbus_method_invocation_return_error (g_steal_pointer (&invocation),
|
||||
G_DBUS_ERROR,
|
||||
G_DBUS_ERROR_FAILED,
|
||||
"Failed to create parse kallsyms");
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(tys)"));
|
||||
while (sysprof_kallsyms_next (kallsyms, &name, &addr, &type))
|
||||
g_variant_builder_add (&builder, "(tys)", addr, type, name);
|
||||
|
||||
ipc_legacy_sysprof2_complete_get_kernel_symbols (service,
|
||||
g_steal_pointer (&invocation),
|
||||
g_variant_builder_end (&builder));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ipc_legacy_impl_g_authorize_method (GDBusInterfaceSkeleton *skeleton,
|
||||
GDBusMethodInvocation *invocation)
|
||||
{
|
||||
PolkitAuthorizationResult *res = NULL;
|
||||
PolkitAuthority *authority = NULL;
|
||||
PolkitSubject *subject = NULL;
|
||||
const gchar *peer_name;
|
||||
gboolean ret = TRUE;
|
||||
|
||||
g_assert (IPC_IS_LEGACY_IMPL (skeleton));
|
||||
g_assert (G_IS_DBUS_METHOD_INVOCATION (invocation));
|
||||
|
||||
g_signal_emit (skeleton, signals [ACTIVITY], 0);
|
||||
|
||||
peer_name = g_dbus_method_invocation_get_sender (invocation);
|
||||
|
||||
if (!(authority = polkit_authority_get_sync (NULL, NULL)) ||
|
||||
!(subject = polkit_system_bus_name_new (peer_name)) ||
|
||||
!(res = polkit_authority_check_authorization_sync (authority,
|
||||
POLKIT_SUBJECT (subject),
|
||||
"org.gnome.sysprof3.profile",
|
||||
NULL,
|
||||
POLKIT_CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION,
|
||||
NULL,
|
||||
NULL)) ||
|
||||
!polkit_authorization_result_get_is_authorized (res))
|
||||
{
|
||||
g_dbus_method_invocation_return_error (g_steal_pointer (&invocation),
|
||||
G_DBUS_ERROR,
|
||||
G_DBUS_ERROR_ACCESS_DENIED,
|
||||
"Not authorized to make request");
|
||||
ret = FALSE;
|
||||
}
|
||||
|
||||
g_clear_object (&authority);
|
||||
g_clear_object (&subject);
|
||||
g_clear_object (&res);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
sysprof2_iface_init (IpcLegacySysprof2Iface *iface)
|
||||
{
|
||||
iface->handle_perf_event_open = ipc_legacy_impl_handle_perf_event_open;
|
||||
iface->handle_get_kernel_symbols = ipc_legacy_impl_handle_get_kernal_symbols;
|
||||
}
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (IpcLegacyImpl, ipc_legacy_impl, IPC_LEGACY_TYPE_SYSPROF2_SKELETON,
|
||||
G_IMPLEMENT_INTERFACE (IPC_LEGACY_TYPE_SYSPROF2, sysprof2_iface_init))
|
||||
|
||||
static void
|
||||
ipc_legacy_impl_class_init (IpcLegacyImplClass *klass)
|
||||
{
|
||||
GDBusInterfaceSkeletonClass *skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass);
|
||||
|
||||
skeleton_class->g_authorize_method = ipc_legacy_impl_g_authorize_method;
|
||||
|
||||
signals [ACTIVITY] =
|
||||
g_signal_new ("activity",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
ipc_legacy_impl_init (IpcLegacyImpl *self)
|
||||
{
|
||||
g_dbus_interface_skeleton_set_flags (G_DBUS_INTERFACE_SKELETON (self),
|
||||
G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD);
|
||||
}
|
||||
|
||||
IpcLegacySysprof2 *
|
||||
ipc_legacy_impl_new (void)
|
||||
{
|
||||
return g_object_new (IPC_TYPE_LEGACY_IMPL, NULL);
|
||||
}
|
||||
@ -1,33 +0,0 @@
|
||||
/* ipc-legacy-impl.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 "ipc-legacy.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define IPC_TYPE_LEGACY_IMPL (ipc_legacy_impl_get_type())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (IpcLegacyImpl, ipc_legacy_impl, IPC, LEGACY_IMPL, IpcLegacySysprof2Skeleton)
|
||||
|
||||
IpcLegacySysprof2 *ipc_legacy_impl_new (void);
|
||||
|
||||
G_END_DECLS
|
||||
@ -1,12 +1,21 @@
|
||||
ipc_profiler_src = gnome.gdbus_codegen('ipc-profiler',
|
||||
sources: '../org.gnome.Sysprof3.Profiler.xml',
|
||||
interface_prefix: 'org.gnome.Sysprof3.',
|
||||
namespace: 'Ipc',
|
||||
)
|
||||
|
||||
ipc_service_src = gnome.gdbus_codegen('ipc-service',
|
||||
sources: '../org.gnome.Sysprof3.Service.xml',
|
||||
interface_prefix: 'org.gnome.Sysprof3.',
|
||||
namespace: 'Ipc',
|
||||
)
|
||||
|
||||
sysprofd_sources = [
|
||||
'../libsysprof/sysprof-kallsyms.c',
|
||||
'sysprofd.c',
|
||||
'ipc-legacy-impl.c',
|
||||
'ipc-rapl-profiler.c',
|
||||
'ipc-service-impl.c',
|
||||
'sysprof-turbostat.c',
|
||||
helpers_sources,
|
||||
ipc_legacy_src,
|
||||
'helpers.c',
|
||||
ipc_profiler_src,
|
||||
ipc_service_src,
|
||||
]
|
||||
@ -26,7 +35,7 @@ sysprofd = executable('sysprofd', sysprofd_sources,
|
||||
install: true,
|
||||
install_dir: pkglibexecdir,
|
||||
pie: true,
|
||||
include_directories: [include_directories('.'), ipc_include_dirs],
|
||||
include_directories: [include_directories('.')],
|
||||
)
|
||||
|
||||
sysprofdconf = configuration_data()
|
||||
@ -69,28 +78,3 @@ i18n.merge_file(
|
||||
install: true,
|
||||
install_dir: join_paths(datadir, 'polkit-1/actions'),
|
||||
)
|
||||
|
||||
#
|
||||
# For org.gnome.Sysprof2 Compatibility
|
||||
#
|
||||
|
||||
configure_file(
|
||||
input: 'org.gnome.Sysprof2.service.in',
|
||||
output: 'org.gnome.Sysprof2.service',
|
||||
configuration: sysprofdconf,
|
||||
install_dir: join_paths(datadir, 'dbus-1/system-services'),
|
||||
)
|
||||
|
||||
configure_file(
|
||||
input: 'org.gnome.Sysprof2.conf.in',
|
||||
output: 'org.gnome.Sysprof2.conf',
|
||||
configuration: sysprofdconf,
|
||||
install_dir: join_paths(datadir, 'dbus-1/system.d'),
|
||||
)
|
||||
|
||||
configure_file(
|
||||
input: 'sysprof2.service.in',
|
||||
output: 'sysprof2.service',
|
||||
configuration: sysprofdconf,
|
||||
install_dir: systemdunitdir,
|
||||
)
|
||||
|
||||
@ -1,19 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<!DOCTYPE busconfig PUBLIC
|
||||
"-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
|
||||
"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
|
||||
<busconfig>
|
||||
<!-- Only root can own the service -->
|
||||
<policy user="root">
|
||||
<allow own="org.gnome.Sysprof2"/>
|
||||
<allow send_destination="org.gnome.Sysprof2"/>
|
||||
<allow receive_sender="org.gnome.Sysprof2"/>
|
||||
</policy>
|
||||
|
||||
<!-- Anyone can send messages to the owner of org.gnome.Sysprof2 -->
|
||||
<policy context="default">
|
||||
<allow send_destination="org.gnome.Sysprof2"/>
|
||||
<allow receive_sender="org.gnome.Sysprof2"/>
|
||||
</policy>
|
||||
</busconfig>
|
||||
@ -1,5 +0,0 @@
|
||||
[D-BUS Service]
|
||||
Name=org.gnome.Sysprof2
|
||||
Exec=@sysprofdprivdir@/sysprofd
|
||||
User=root
|
||||
SystemdService=sysprof2.service
|
||||
@ -1,8 +0,0 @@
|
||||
[Unit]
|
||||
Description=Sysprof Daemon
|
||||
|
||||
[Service]
|
||||
Type=dbus
|
||||
BusName=org.gnome.Sysprof2
|
||||
ExecStart=@sysprofdprivdir@/sysprofd
|
||||
|
||||
@ -26,10 +26,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <sysprof-capture.h>
|
||||
|
||||
#include "ipc-legacy.h"
|
||||
#include "ipc-service.h"
|
||||
|
||||
#include "ipc-legacy-impl.h"
|
||||
#include "ipc-rapl-profiler.h"
|
||||
#include "ipc-service-impl.h"
|
||||
|
||||
@ -127,18 +125,15 @@ main (gint argc,
|
||||
|
||||
if ((bus = g_bus_get_sync (bus_type, NULL, &error)))
|
||||
{
|
||||
g_autoptr(IpcLegacySysprof2) v2_service = ipc_legacy_impl_new ();
|
||||
g_autoptr(IpcProfiler) rapl = ipc_rapl_profiler_new ();
|
||||
g_autoptr(IpcService) v3_service = ipc_service_impl_new ();
|
||||
|
||||
g_signal_connect (v3_service, "activity", G_CALLBACK (activity_cb), NULL);
|
||||
g_signal_connect (v2_service, "activity", G_CALLBACK (activity_cb), NULL);
|
||||
g_signal_connect (rapl, "activity", G_CALLBACK (activity_cb), NULL);
|
||||
|
||||
activity_cb (NULL, NULL);
|
||||
|
||||
if (g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (v3_service), bus, V3_PATH, &error) &&
|
||||
g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (v2_service), bus, V2_PATH, &error) &&
|
||||
g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (rapl), bus, RAPL_PATH, &error))
|
||||
{
|
||||
for (guint i = 0; i < G_N_ELEMENTS (bus_names); i++)
|
||||
|
||||
@ -1,6 +0,0 @@
|
||||
#sysprof_cli = executable('sysprof-cli', 'sysprof-cli.c',
|
||||
# dependencies: [libsysprof_static_dep, polkit_dep, polkit_agent_dep],
|
||||
# c_args: tools_cflags,
|
||||
# install_dir: get_option('bindir'),
|
||||
# install: true,
|
||||
#)
|
||||
@ -1,445 +0,0 @@
|
||||
/* sysprof-dump.c
|
||||
*
|
||||
* Copyright 2016-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
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include <sysprof-capture.h>
|
||||
#include <sysprof.h>
|
||||
|
||||
static gboolean list_files = FALSE;
|
||||
static gboolean resolve = FALSE;
|
||||
static const GOptionEntry main_entries[] = {
|
||||
{ "list-files", 'l', 0, G_OPTION_ARG_NONE, &list_files, "List files within the capture" },
|
||||
{ "resolve", 'r', 0, G_OPTION_ARG_NONE, &resolve, "Resolve symbols" },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static char *
|
||||
symbolize (GPtrArray *resolvers,
|
||||
const SysprofCaptureFrame *frame,
|
||||
SysprofAddressContext *context,
|
||||
SysprofAddress address)
|
||||
{
|
||||
SysprofAddressContext last_context = *context;
|
||||
|
||||
if (sysprof_address_is_context_switch (address, context))
|
||||
return g_strdup (sysprof_address_context_to_string (last_context));
|
||||
|
||||
if (last_context == SYSPROF_ADDRESS_CONTEXT_NONE)
|
||||
last_context = SYSPROF_ADDRESS_CONTEXT_USER;
|
||||
|
||||
for (guint j = 0; j < resolvers->len; j++)
|
||||
{
|
||||
SysprofSymbolResolver *resolver = g_ptr_array_index (resolvers, j);
|
||||
GQuark tag = 0;
|
||||
char *str;
|
||||
|
||||
str = sysprof_symbol_resolver_resolve_with_context (resolver, frame->time, frame->pid, last_context, address, &tag);
|
||||
|
||||
if (str != NULL)
|
||||
return str;
|
||||
}
|
||||
|
||||
return g_strdup ("??");
|
||||
}
|
||||
|
||||
gint
|
||||
main (gint argc,
|
||||
gchar *argv[])
|
||||
{
|
||||
g_autoptr(GOptionContext) option_context = g_option_context_new ("- dump capture data");
|
||||
g_autoptr(GPtrArray) resolvers = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
SysprofCaptureReader *reader;
|
||||
SysprofCaptureFrameType type;
|
||||
GHashTable *ctrtypes;
|
||||
gint64 begin_time;
|
||||
gint64 end_time;
|
||||
|
||||
g_option_context_add_main_entries (option_context, main_entries, NULL);
|
||||
if (!g_option_context_parse (option_context, &argc, &argv, &error))
|
||||
{
|
||||
g_printerr ("%s\n", error->message);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
g_printerr ("usage: %s FILENAME\n", argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if ((reader = sysprof_capture_reader_new (argv[1])) == NULL)
|
||||
{
|
||||
int errsv = errno;
|
||||
g_printerr ("%s\n", g_strerror (errsv));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (list_files)
|
||||
{
|
||||
g_autofree const gchar **files = sysprof_capture_reader_list_files (reader);
|
||||
|
||||
for (gsize i = 0; files[i]; i++)
|
||||
g_print ("%s\n", files[i]);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
resolvers = g_ptr_array_new_with_free_func (g_object_unref);
|
||||
|
||||
if (resolve)
|
||||
{
|
||||
g_ptr_array_add (resolvers, sysprof_capture_symbol_resolver_new ());
|
||||
g_ptr_array_add (resolvers, sysprof_kernel_symbol_resolver_new ());
|
||||
g_ptr_array_add (resolvers, sysprof_elf_symbol_resolver_new ());
|
||||
|
||||
for (guint i = 0; i < resolvers->len; i++)
|
||||
{
|
||||
sysprof_symbol_resolver_load (g_ptr_array_index (resolvers, i), reader);
|
||||
sysprof_capture_reader_reset (reader);
|
||||
}
|
||||
}
|
||||
|
||||
ctrtypes = g_hash_table_new (NULL, NULL);
|
||||
|
||||
begin_time = sysprof_capture_reader_get_start_time (reader);
|
||||
|
||||
#define SET_CTR_TYPE(i,t) g_hash_table_insert(ctrtypes, GINT_TO_POINTER(i), GINT_TO_POINTER(t))
|
||||
#define GET_CTR_TYPE(i) GPOINTER_TO_INT(g_hash_table_lookup(ctrtypes, GINT_TO_POINTER(i)))
|
||||
|
||||
begin_time = sysprof_capture_reader_get_start_time (reader);
|
||||
end_time = sysprof_capture_reader_get_end_time (reader);
|
||||
|
||||
g_print ("Capture Time Range: %" G_GUINT64_FORMAT " to %" G_GUINT64_FORMAT " (%lf)\n",
|
||||
begin_time, end_time, (end_time - begin_time) / (gdouble)SYSPROF_NSEC_PER_SEC);
|
||||
|
||||
while (sysprof_capture_reader_peek_type (reader, &type))
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case SYSPROF_CAPTURE_FRAME_EXIT:
|
||||
{
|
||||
const SysprofCaptureExit *ex = sysprof_capture_reader_read_exit (reader);
|
||||
|
||||
if (ex == NULL)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
g_print ("EXIT: pid=%d\n", ex->frame.pid);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SYSPROF_CAPTURE_FRAME_FORK:
|
||||
{
|
||||
const SysprofCaptureFork *fk = sysprof_capture_reader_read_fork (reader);
|
||||
|
||||
if (fk == NULL)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
g_print ("FORK: pid=%d child_pid=%d\n", fk->frame.pid, fk->child_pid);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SYSPROF_CAPTURE_FRAME_OVERLAY:
|
||||
{
|
||||
const SysprofCaptureOverlay *pr = sysprof_capture_reader_read_overlay (reader);
|
||||
const char *src = pr->data;
|
||||
const char *dst = &pr->data[pr->src_len+1];
|
||||
|
||||
if (pr == NULL)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
g_print ("OVERLAY: pid=%d layer=%u src=%s dst=%s\n", pr->frame.pid, pr->layer, src, dst);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SYSPROF_CAPTURE_FRAME_JITMAP:
|
||||
{
|
||||
const SysprofCaptureJitmap *jitmap = sysprof_capture_reader_read_jitmap (reader);
|
||||
SysprofCaptureJitmapIter iter;
|
||||
SysprofCaptureAddress addr;
|
||||
const gchar *str;
|
||||
|
||||
if (jitmap == NULL)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
g_print ("JITMAP:\n");
|
||||
|
||||
sysprof_capture_jitmap_iter_init (&iter, jitmap);
|
||||
while (sysprof_capture_jitmap_iter_next (&iter, &addr, &str))
|
||||
g_print (" " SYSPROF_CAPTURE_ADDRESS_FORMAT " : %s\n", addr, str);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SYSPROF_CAPTURE_FRAME_LOG:
|
||||
{
|
||||
const SysprofCaptureLog *log = sysprof_capture_reader_read_log (reader);
|
||||
gdouble ptime = (log->frame.time - begin_time) / (gdouble)SYSPROF_NSEC_PER_SEC;
|
||||
|
||||
g_print ("LOG: pid=%d time=%" G_GINT64_FORMAT " (%lf)\n"
|
||||
" severity = %d\n"
|
||||
" domain = %s\n"
|
||||
" message = %s\n",
|
||||
log->frame.pid, log->frame.time, ptime,
|
||||
log->severity, log->domain, log->message);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SYSPROF_CAPTURE_FRAME_MAP:
|
||||
{
|
||||
const SysprofCaptureMap *map = sysprof_capture_reader_read_map (reader);
|
||||
|
||||
g_print ("MAP: pid=%d time=%" G_GINT64_FORMAT "\n"
|
||||
" start = %" G_GUINT64_FORMAT "\n"
|
||||
" end = %" G_GUINT64_FORMAT "\n"
|
||||
" offset = %" G_GUINT64_FORMAT "\n"
|
||||
" inode = %" G_GUINT64_FORMAT "\n"
|
||||
" filename = %s\n",
|
||||
map->frame.pid, map->frame.time,
|
||||
map->start, map->end, map->offset, map->inode, map->filename);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SYSPROF_CAPTURE_FRAME_FILE_CHUNK:
|
||||
{
|
||||
const SysprofCaptureFileChunk *file_chunk = sysprof_capture_reader_read_file (reader);
|
||||
gdouble ptime = (file_chunk->frame.time - begin_time) / (gdouble)SYSPROF_NSEC_PER_SEC;
|
||||
|
||||
g_print ("FILE_CHUNK: pid=%d time=%" G_GINT64_FORMAT " (%lf)\n"
|
||||
" path = %s\n"
|
||||
" is_last = %d\n"
|
||||
" bytes = %d\n",
|
||||
file_chunk->frame.pid, file_chunk->frame.time, ptime,
|
||||
file_chunk->path, file_chunk->is_last, file_chunk->len);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SYSPROF_CAPTURE_FRAME_MARK:
|
||||
{
|
||||
const SysprofCaptureMark *mark = sysprof_capture_reader_read_mark (reader);
|
||||
gdouble ptime = (mark->frame.time - begin_time) / (gdouble)SYSPROF_NSEC_PER_SEC;
|
||||
|
||||
g_print ("MARK: pid=%d time=%" G_GINT64_FORMAT " (%lf)\n"
|
||||
" group = %s\n"
|
||||
" name = %s\n"
|
||||
" duration = %" G_GUINT64_FORMAT "\n"
|
||||
" message = %s\n",
|
||||
mark->frame.pid, mark->frame.time, ptime,
|
||||
mark->group, mark->name, mark->duration, mark->message);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SYSPROF_CAPTURE_FRAME_METADATA:
|
||||
{
|
||||
const SysprofCaptureMetadata *metadata = sysprof_capture_reader_read_metadata (reader);
|
||||
gdouble ptime = (metadata->frame.time - begin_time) / (gdouble)SYSPROF_NSEC_PER_SEC;
|
||||
|
||||
g_print ("METADATA: pid=%d time=%" G_GINT64_FORMAT " (%lf)\n"
|
||||
" id = %s\n"
|
||||
"\"\"\"\n%s\n\"\"\"\n",
|
||||
metadata->frame.pid, metadata->frame.time, ptime,
|
||||
metadata->id, metadata->metadata);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SYSPROF_CAPTURE_FRAME_PROCESS:
|
||||
{
|
||||
const SysprofCaptureProcess *pr = sysprof_capture_reader_read_process (reader);
|
||||
|
||||
if (pr == NULL)
|
||||
perror ("Failed to read process");
|
||||
|
||||
g_print ("PROCESS: pid=%d cmdline=%s time=%" G_GINT64_FORMAT "\n", pr->frame.pid, pr->cmdline, pr->frame.time);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SYSPROF_CAPTURE_FRAME_SAMPLE:
|
||||
{
|
||||
const SysprofCaptureSample *s = sysprof_capture_reader_read_sample (reader);
|
||||
gdouble ptime = (s->frame.time - begin_time) / (gdouble)SYSPROF_NSEC_PER_SEC;
|
||||
SysprofAddressContext context = SYSPROF_ADDRESS_CONTEXT_NONE;
|
||||
|
||||
g_print ("SAMPLE: pid=%d tid=%d time=%" G_GINT64_FORMAT " (%lf)\n",
|
||||
s->frame.pid, s->tid, s->frame.time, ptime);
|
||||
|
||||
for (guint i = 0; i < s->n_addrs; i++)
|
||||
{
|
||||
if (resolve)
|
||||
{
|
||||
g_autofree char *name = symbolize (resolvers, &s->frame, &context, s->addrs[i]);
|
||||
g_print (" " SYSPROF_CAPTURE_ADDRESS_FORMAT " (%s)\n", s->addrs[i], name);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_print (" " SYSPROF_CAPTURE_ADDRESS_FORMAT "\n", s->addrs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SYSPROF_CAPTURE_FRAME_TRACE:
|
||||
{
|
||||
const SysprofCaptureTrace *s = sysprof_capture_reader_read_trace (reader);
|
||||
gdouble ptime = (s->frame.time - begin_time) / (gdouble)SYSPROF_NSEC_PER_SEC;
|
||||
SysprofAddressContext context = SYSPROF_ADDRESS_CONTEXT_NONE;
|
||||
|
||||
g_print ("TRACE: pid=%d tid=%d time=%" G_GINT64_FORMAT " (%lf) %s\n",
|
||||
s->frame.pid, s->tid, s->frame.time, ptime,
|
||||
s->entering ? "ENTER" : "EXIT");
|
||||
|
||||
for (guint i = 0; i < s->n_addrs; i++)
|
||||
{
|
||||
if (resolve)
|
||||
{
|
||||
g_autofree char *name = symbolize (resolvers, &s->frame, &context, s->addrs[i]);
|
||||
g_print (" " SYSPROF_CAPTURE_ADDRESS_FORMAT " (%s)\n", s->addrs[i], name);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_print (" " SYSPROF_CAPTURE_ADDRESS_FORMAT "\n", s->addrs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SYSPROF_CAPTURE_FRAME_TIMESTAMP:
|
||||
{
|
||||
const SysprofCaptureTimestamp *ts = sysprof_capture_reader_read_timestamp (reader);
|
||||
g_print ("TIMESTAMP: pid=%d time=%" G_GINT64_FORMAT "\n", ts->frame.pid, ts->frame.time);
|
||||
break;
|
||||
}
|
||||
|
||||
case SYSPROF_CAPTURE_FRAME_CTRDEF:
|
||||
{
|
||||
const SysprofCaptureCounterDefine *def = sysprof_capture_reader_read_counter_define (reader);
|
||||
gdouble ptime = (def->frame.time - begin_time) / (gdouble)SYSPROF_NSEC_PER_SEC;
|
||||
guint i;
|
||||
|
||||
g_print ("NEW COUNTERS: pid=%d time=%" G_GINT64_FORMAT " (%lf)\n", def->frame.pid, def->frame.time, ptime);
|
||||
|
||||
for (i = 0; i < def->n_counters; i++)
|
||||
{
|
||||
const SysprofCaptureCounter *ctr = &def->counters[i];
|
||||
|
||||
SET_CTR_TYPE (ctr->id, ctr->type);
|
||||
|
||||
g_print (" COUNTER(%03d<%s>): %s\n"
|
||||
" %s\n"
|
||||
" %s\n"
|
||||
"\n",
|
||||
ctr->id,
|
||||
ctr->type == SYSPROF_CAPTURE_COUNTER_INT64 ? "i64" : "f64",
|
||||
ctr->category,
|
||||
ctr->name,
|
||||
ctr->description);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SYSPROF_CAPTURE_FRAME_CTRSET:
|
||||
{
|
||||
const SysprofCaptureCounterSet *set = sysprof_capture_reader_read_counter_set (reader);
|
||||
gdouble ptime = (set->frame.time - begin_time) / (gdouble)SYSPROF_NSEC_PER_SEC;
|
||||
guint i;
|
||||
|
||||
g_print ("SET COUNTERS: pid=%d time=%" G_GINT64_FORMAT " (%lf)\n", set->frame.pid, set->frame.time, ptime);
|
||||
|
||||
for (i = 0; i < set->n_values; i++)
|
||||
{
|
||||
const SysprofCaptureCounterValues *values = &set->values[i];
|
||||
guint j;
|
||||
|
||||
for (j = 0; j < G_N_ELEMENTS (values->ids); j++)
|
||||
{
|
||||
if (values->ids[j])
|
||||
{
|
||||
if (GET_CTR_TYPE (values->ids[j]) == SYSPROF_CAPTURE_COUNTER_INT64)
|
||||
g_print (" COUNTER(%d): %" G_GINT64_FORMAT "\n",
|
||||
values->ids[j],
|
||||
values->values[j].v64);
|
||||
else if (GET_CTR_TYPE (values->ids[j]) == SYSPROF_CAPTURE_COUNTER_DOUBLE)
|
||||
g_print (" COUNTER(%d): %lf\n",
|
||||
values->ids[j],
|
||||
values->values[j].vdbl);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SYSPROF_CAPTURE_FRAME_ALLOCATION:
|
||||
{
|
||||
const SysprofCaptureAllocation *ev = sysprof_capture_reader_read_allocation (reader);
|
||||
gdouble ptime = (ev->frame.time - begin_time) / (gdouble)SYSPROF_NSEC_PER_SEC;
|
||||
SysprofAddressContext context = SYSPROF_ADDRESS_CONTEXT_NONE;
|
||||
|
||||
g_print ("%s: pid=%d tid=%d addr=0x%" G_GINT64_MODIFIER "x size=%" G_GINT64_FORMAT " time=%" G_GINT64_FORMAT " (%lf)\n",
|
||||
ev->alloc_size > 0 ? "ALLOC" : "FREE",
|
||||
ev->frame.pid, ev->tid,
|
||||
ev->alloc_addr, ev->alloc_size,
|
||||
ev->frame.time, ptime);
|
||||
|
||||
for (guint i = 0; i < ev->n_addrs; i++)
|
||||
{
|
||||
if (resolve)
|
||||
{
|
||||
g_autofree char *name = symbolize (resolvers, &ev->frame, &context, ev->addrs[i]);
|
||||
g_print (" " SYSPROF_CAPTURE_ADDRESS_FORMAT " (%s)\n", ev->addrs[i], name);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_print (" " SYSPROF_CAPTURE_ADDRESS_FORMAT "\n", ev->addrs[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
g_print ("Skipping unknown frame type: (%d): ", type);
|
||||
if (!sysprof_capture_reader_skip (reader))
|
||||
{
|
||||
g_print ("Failed\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
g_print ("Success\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@ -1,197 +0,0 @@
|
||||
/* sysprof-profiler-ctl.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-profiler-ctl"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <glib-unix.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <gio/gunixfdlist.h>
|
||||
#include <stdlib.h>
|
||||
#include <gio/gio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "ipc-profiler.h"
|
||||
|
||||
static gboolean opt_force;
|
||||
static gboolean opt_system;
|
||||
static gboolean opt_session;
|
||||
static gchar *opt_address;
|
||||
static gchar *opt_dest;
|
||||
static gchar *opt_object_path;
|
||||
static gint opt_timeout = -1;
|
||||
|
||||
static const GOptionEntry main_entries[] = {
|
||||
{ "system", 'y', 0, G_OPTION_ARG_NONE, &opt_system, N_("Connect to the system bus") },
|
||||
{ "session", 'e', 0, G_OPTION_ARG_NONE, &opt_session, N_("Connect to the session bus") },
|
||||
{ "address", 'a', 0, G_OPTION_ARG_STRING, &opt_address, N_("Connect to the given D-Bus address") },
|
||||
{ "dest", 'd', 0, G_OPTION_ARG_STRING, &opt_dest, N_("Destination D-Bus name to invoke method on") },
|
||||
{ "object-path", 'o', 0, G_OPTION_ARG_STRING, &opt_object_path, N_("Object path to invoke method on"), N_("/org/gnome/Sysprof3/Profiler") },
|
||||
{ "timeout", 't', 0, G_OPTION_ARG_INT, &opt_timeout, N_("Timeout in seconds") },
|
||||
{ "force", 'f', 0, G_OPTION_ARG_NONE, &opt_force, N_("Overwrite FILENAME if it exists") },
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static gboolean
|
||||
handle_sigint (gpointer data)
|
||||
{
|
||||
GMainLoop *main_loop = data;
|
||||
g_printerr ("\nSIGINT received, stopping profiler.\n");
|
||||
g_main_loop_quit (main_loop);
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
gint
|
||||
main (gint argc,
|
||||
gchar *argv[])
|
||||
{
|
||||
g_autoptr(GOptionContext) context = NULL;
|
||||
g_autoptr(GDBusConnection) bus = NULL;
|
||||
g_autoptr(GUnixFDList) fd_list = NULL;
|
||||
g_autoptr(GVariant) reply = NULL;
|
||||
g_autoptr(GError) error = NULL;
|
||||
g_autoptr(GMainLoop) main_loop = NULL;
|
||||
g_autofree gchar *filename = NULL;
|
||||
guint flags = O_RDWR;
|
||||
gint fd;
|
||||
gint handle;
|
||||
|
||||
context = g_option_context_new (_("--dest=BUS_NAME [FILENAME] - connect to an embedded sysprof profiler"));
|
||||
g_option_context_add_main_entries (context, main_entries, GETTEXT_PACKAGE);
|
||||
|
||||
if (!g_option_context_parse (context, &argc, &argv, &error))
|
||||
{
|
||||
g_printerr ("%s\n", error->message);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (opt_dest == NULL)
|
||||
{
|
||||
g_printerr ("--dest= must contain a peer bus name on the D-Bus.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if ((opt_system && opt_session) ||
|
||||
(opt_address && (opt_system || opt_session)))
|
||||
{
|
||||
g_printerr ("Only one of --system --session or --address may be specified.");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!opt_address && !opt_session && !opt_system)
|
||||
opt_session = TRUE;
|
||||
|
||||
main_loop = g_main_loop_new (NULL, FALSE);
|
||||
g_unix_signal_add (SIGINT, handle_sigint, main_loop);
|
||||
|
||||
if (opt_session)
|
||||
bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
|
||||
else if (opt_system)
|
||||
bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
|
||||
else
|
||||
bus = g_dbus_connection_new_for_address_sync (opt_address,
|
||||
G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
|
||||
NULL,
|
||||
NULL,
|
||||
&error);
|
||||
|
||||
if (bus == NULL)
|
||||
{
|
||||
g_printerr ("Failed to connect to D-Bus: %s\n", error->message);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
filename = (argc == 1) ? g_strdup_printf ("sysprof.%d.syscap", getpid ())
|
||||
: g_strdup (argv[1]);
|
||||
|
||||
if (!opt_force)
|
||||
flags |= O_CREAT;
|
||||
|
||||
if (-1 == (fd = g_open (filename, flags, 0644)))
|
||||
{
|
||||
g_printerr ("Failed to open file \"%s\". Try --force.\n", filename);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
fd_list = g_unix_fd_list_new ();
|
||||
handle = g_unix_fd_list_append (fd_list, fd, &error);
|
||||
|
||||
close (fd);
|
||||
fd = -1;
|
||||
|
||||
if (handle == -1)
|
||||
{
|
||||
g_printerr ("Failed to build FD list for peer.\n");
|
||||
g_unlink (filename);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
reply = g_dbus_connection_call_with_unix_fd_list_sync (bus,
|
||||
opt_dest,
|
||||
opt_object_path,
|
||||
"org.gnome.Sysprof3.Profiler",
|
||||
"Start",
|
||||
g_variant_new ("(a{sv}h)", NULL, handle),
|
||||
G_VARIANT_TYPE ("()"),
|
||||
G_DBUS_CALL_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION,
|
||||
opt_timeout,
|
||||
fd_list,
|
||||
NULL,
|
||||
NULL,
|
||||
&error);
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
g_printerr ("Failed to start profiler: %s\n", error->message);
|
||||
g_unlink (filename);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
g_printerr ("Profiler capturing to file \"%s\"\n", filename);
|
||||
|
||||
g_clear_pointer (&reply, g_variant_unref);
|
||||
|
||||
g_main_loop_run (main_loop);
|
||||
|
||||
reply = g_dbus_connection_call_sync (bus,
|
||||
opt_dest,
|
||||
opt_object_path,
|
||||
"org.gnome.Sysprof3.Profiler",
|
||||
"Stop",
|
||||
g_variant_new ("()"),
|
||||
NULL,
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
opt_timeout,
|
||||
NULL,
|
||||
&error);
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
g_printerr ("Failed to stop profiler: %s\n", error->message);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
g_printerr ("Profiler stopped.\n");
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
Reference in New Issue
Block a user