From fa13c41da7fb03a710bfd8840cae4bb57cf14829 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Thu, 25 Jun 2020 22:08:05 +0100 Subject: [PATCH 1/5] gtrace: Add sysprof tracing support infrastructure Add some internal wrappers around sysprof tracing, so that it can be used throughout GLib without exposing all the details of sysprof internally. This adds an optional dependency on `libsysprof-capture-4`. sysprof support is disabled without it. This depends on the GLib dependency of `libsysprof-capture` being dropped in https://gitlab.gnome.org/GNOME/sysprof/-/merge_requests/30, which has bumped the soname of `libsysprof-capture` and added subproject support. The next few commits will add marks that trace out each `GMainContext` iteration and each `GSource` `check`/`prepare`/`dispatch` call. Signed-off-by: Philip Withnall --- docs/reference/glib/meson.build | 1 + glib/gtrace-private.h | 70 +++++++++++++++++++++++ glib/gtrace.c | 98 +++++++++++++++++++++++++++++++++ glib/meson.build | 20 ++++++- meson_options.txt | 5 ++ subprojects/sysprof.wrap | 4 ++ 6 files changed, 197 insertions(+), 1 deletion(-) create mode 100644 glib/gtrace-private.h create mode 100644 glib/gtrace.c create mode 100644 subprojects/sysprof.wrap diff --git a/docs/reference/glib/meson.build b/docs/reference/glib/meson.build index 62d95f78d..43c273855 100644 --- a/docs/reference/glib/meson.build +++ b/docs/reference/glib/meson.build @@ -22,6 +22,7 @@ if get_option('gtk_doc') 'gprintfint.h', 'gmirroringtable.h', 'gscripttable.h', + 'gtrace-private.h', 'glib-mirroring-tab', 'gnulib', 'pcre', diff --git a/glib/gtrace-private.h b/glib/gtrace-private.h new file mode 100644 index 000000000..24550152d --- /dev/null +++ b/glib/gtrace-private.h @@ -0,0 +1,70 @@ +/* + * Copyright © 2020 Endless Mobile, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + * Author: Philip Withnall + */ + +#pragma once + +#ifdef HAVE_SYSPROF +#include +#endif + +#include "gmem.h" +#include "gmacros.h" + +G_BEGIN_DECLS + +/* + * G_TRACE_CURRENT_TIME: + * + * Get the current time, in nanoseconds since the tracing epoch. This (and only + * this) is suitable for passing to tracing functions like g_trace_mark(). It is + * not suitable for other timekeeping. + * + * The tracing epoch is implementation defined, but is guaranteed to be + * unchanged within the lifetime of each thread. It is not comparable across + * threads or process instances. + * + * If tracing support is disabled, this evaluates to `0`. + * + * Since: 2.66 + */ +#ifdef HAVE_SYSPROF +#define G_TRACE_CURRENT_TIME SYSPROF_CAPTURE_CURRENT_TIME +#else +#define G_TRACE_CURRENT_TIME 0 +#endif + +void (g_trace_mark) (gint64 begin_time_nsec, + gint64 duration_nsec, + const gchar *group, + const gchar *name, + const gchar *message_format, + ...); + +#ifndef HAVE_SYSPROF +/* Optimise the whole call out */ +#if defined(G_HAVE_ISO_VARARGS) +#define g_trace_mark(b, d, g, n, m, ...) +#elif defined(G_HAVE_GNUC_VARARGS) +#define g_trace_mark(b, d, g, n, m...) +#else +/* no varargs macro support; the call will have to be optimised out by the compiler */ +#endif +#endif + +G_END_DECLS diff --git a/glib/gtrace.c b/glib/gtrace.c new file mode 100644 index 000000000..29726778d --- /dev/null +++ b/glib/gtrace.c @@ -0,0 +1,98 @@ +/* + * Copyright © 2020 Endless Mobile, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + * + * Author: Philip Withnall + */ + +/* + * SECTION:trace + * @Title: Performance tracing + * @Short_description: Functions for measuring and tracing performance + * + * The performance tracing functions allow for the performance of code using + * GLib to be measured by passing metrics from the current process to an + * external measurement process such as `sysprof-cli` or `sysprofd`. + * + * They are designed to execute quickly, especially in the common case where no + * measurement process is connected. They are guaranteed to not block the caller + * and are guaranteed to have zero runtime cost if tracing support is disabled + * at configure time. + * + * Tracing information can be provided as ‘marks’ with a start time and + * duration; or as marks with a start time and no duration. Marks with a + * duration are intended to show the execution time of a piece of code. Marks + * with no duration are intended to show an instantaneous performance problem, + * such as an unexpectedly large allocation, or that a slow path has been taken + * in some code. + * + * |[ + * gint64 begin_time_nsec G_GNUC_UNUSED; + * + * begin_time_nsec = G_TRACE_CURRENT_TIME; + * + * // some code which might take a while + * + * g_trace_mark (begin_time_nsec, G_TRACE_CURRENT_TIME - begin_time_nsec, + * "GLib", "GSource.dispatch", + * "%s ⇒ %s", g_source_get_name (source), need_destroy ? "destroy" : "keep"); + * ]| + * + * The tracing API is currently internal to GLib. + * + * Since: 2.66 + */ + +#include "config.h" + +#include "gtrace-private.h" + +#include + +/* + * g_trace_mark: + * @begin_time_nsec: start time of the mark, as returned by %G_TRACE_CURRENT_TIME + * @duration_nsec: duration of the mark, in nanoseconds + * @group: name of the group for categorising this mark + * @name: name of the mark + * @message_format: format for the detailed message for the mark, in `printf()` format + * @...: arguments to substitute into @message_format; none of these should have + * side effects + * + * Add a mark to the trace, starting at @begin_time_nsec and having length + * @duration_nsec (which may be zero). The @group should typically be `GLib`, + * and the @name should concisely describe the call site. + * + * All of the arguments to this function must not have side effects, as the + * entire function call may be dropped if sysprof support is not available. + * + * Since: 2.66 + */ +void +(g_trace_mark) (gint64 begin_time_nsec, + gint64 duration_nsec, + const gchar *group, + const gchar *name, + const gchar *message_format, + ...) +{ +#ifdef HAVE_SYSPROF + va_list args; + + va_start (args, message_format); + sysprof_collector_mark_vprintf (begin_time_nsec, duration_nsec, group, name, message_format, args); + va_end (args); +#endif /* HAVE_SYSPROF */ +} diff --git a/glib/meson.build b/glib/meson.build index 149d62f01..7e0edb905 100644 --- a/glib/meson.build +++ b/glib/meson.build @@ -7,6 +7,22 @@ if not use_system_pcre subdir('pcre') endif +# libsysprof-capture support +libsysprof_capture_dep = dependency('sysprof-capture-4', + required: get_option('sysprof'), + default_options: [ + 'enable_examples=false', + 'enable_gtk=false', + 'enable_tests=false', + 'enable_tools=false', + 'libsysprof=false', + 'with_sysprofd=none', + 'help=false', + ], + fallback: ['sysprof', 'libsysprof_capture_dep'], +) +glib_conf.set('HAVE_SYSPROF', libsysprof_capture_dep.found()) + # TODO: gnulib_objects, pcre_objects and pcre_deps are a workaround for # and # . When we can depend @@ -275,6 +291,8 @@ glib_sources = files( 'gthreadpool.c', 'gtimer.c', 'gtimezone.c', + 'gtrace.c', + 'gtrace-private.h', 'gtranslit.c', 'gtrashstack.c', 'gtree.c', @@ -357,7 +375,7 @@ libglib = library('glib-2.0', # intl.lib is not compatible with SAFESEH link_args : [noseh_link_args, glib_link_flags, win32_ldflags], include_directories : configinc, - dependencies : pcre_deps + [thread_dep, librt] + libintl_deps + libiconv + platform_deps + gnulib_libm_dependency, + dependencies : pcre_deps + [thread_dep, librt] + libintl_deps + libiconv + platform_deps + gnulib_libm_dependency + [libsysprof_capture_dep], c_args : glib_c_args, objc_args : glib_c_args, ) diff --git a/meson_options.txt b/meson_options.txt index 80a1d9d8f..c6f228a01 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -59,6 +59,11 @@ option('tapset_install_dir', value : '', description : 'path where systemtap tapsets are installed') +option('sysprof', + type : 'feature', + value : 'disabled', + description : 'include tracing support for sysprof') + option('gtk_doc', type : 'boolean', value : false, diff --git a/subprojects/sysprof.wrap b/subprojects/sysprof.wrap new file mode 100644 index 000000000..14874880e --- /dev/null +++ b/subprojects/sysprof.wrap @@ -0,0 +1,4 @@ +[wrap-git] +directory=sysprof +url=https://gitlab.gnome.org/GNOME/sysprof.git +revision=6b1cd7a722fcebae1ac392562c47957477ade8bf From bfe161742cc2b25ff9c22d69509b7b3580f6e4c4 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Thu, 25 Jun 2020 22:23:17 +0100 Subject: [PATCH 2/5] gmain: Add sysprof tracing to GMainContext and GSource MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows you to see how long each `GMainContext` iteration and each `GSource` `check`/`prepare`/`dispatch` takes. It provides more detail than sysprof’s speedtrack plugin can provide, since it has access to more internal GLib data. Use it with `sysprof-cli`, for example: ``` sysprof-cli --use-trace-fd -- my-test-program ``` Signed-off-by: Philip Withnall --- glib/gmain.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/glib/gmain.c b/glib/gmain.c index c18d29079..34ed594ca 100644 --- a/glib/gmain.c +++ b/glib/gmain.c @@ -88,6 +88,7 @@ #include "gstrfuncs.h" #include "gtestutils.h" #include "gthreadprivate.h" +#include "gtrace-private.h" #ifdef G_OS_WIN32 #include "gwin32.h" @@ -1248,6 +1249,12 @@ g_source_attach_unlocked (GSource *source, if (do_wakeup && context->owner && context->owner != G_THREAD_SELF) g_wakeup_signal (context->wakeup); + g_trace_mark (G_TRACE_CURRENT_TIME, 0, + "GLib", "g_source_attach", + "%s to context %p", + (g_source_get_name (source) != NULL) ? g_source_get_name (source) : "(unnamed)", + context); + return source->source_id; } @@ -3291,6 +3298,7 @@ g_main_dispatch (GMainContext *context) GSourceFunc, gpointer); GSource *prev_source; + gint64 begin_time_nsec G_GNUC_UNUSED; dispatch = source->source_funcs->dispatch; cb_funcs = source->callback_funcs; @@ -3317,12 +3325,20 @@ g_main_dispatch (GMainContext *context) current->source = source; current->depth++; + begin_time_nsec = G_TRACE_CURRENT_TIME; + TRACE (GLIB_MAIN_BEFORE_DISPATCH (g_source_get_name (source), source, dispatch, callback, user_data)); need_destroy = !(* dispatch) (source, callback, user_data); TRACE (GLIB_MAIN_AFTER_DISPATCH (g_source_get_name (source), source, dispatch, need_destroy)); + g_trace_mark (begin_time_nsec, G_TRACE_CURRENT_TIME - begin_time_nsec, + "GLib", "GSource.dispatch", + "%s ⇒ %s", + (g_source_get_name (source) != NULL) ? g_source_get_name (source) : "(unnamed)", + need_destroy ? "destroy" : "keep"); + current->source = prev_source; current->depth--; @@ -3626,12 +3642,22 @@ g_main_context_prepare (GMainContext *context, if (prepare) { + gint64 begin_time_nsec G_GNUC_UNUSED; + context->in_check_or_prepare++; UNLOCK_CONTEXT (context); + begin_time_nsec = G_TRACE_CURRENT_TIME; + result = (* prepare) (source, &source_timeout); TRACE (GLIB_MAIN_AFTER_PREPARE (source, prepare, source_timeout)); + g_trace_mark (begin_time_nsec, G_TRACE_CURRENT_TIME - begin_time_nsec, + "GLib", "GSource.prepare", + "%s ⇒ %s", + (g_source_get_name (source) != NULL) ? g_source_get_name (source) : "(unnamed)", + result ? "ready" : "unready"); + LOCK_CONTEXT (context); context->in_check_or_prepare--; } @@ -3886,14 +3912,24 @@ g_main_context_check (GMainContext *context, if (check) { + gint64 begin_time_nsec G_GNUC_UNUSED; + /* If the check function is set, call it. */ context->in_check_or_prepare++; UNLOCK_CONTEXT (context); + begin_time_nsec = G_TRACE_CURRENT_TIME; + result = (* check) (source); TRACE (GLIB_MAIN_AFTER_CHECK (source, check, result)); + g_trace_mark (begin_time_nsec, G_TRACE_CURRENT_TIME - begin_time_nsec, + "GLib", "GSource.check", + "%s ⇒ %s", + (g_source_get_name (source) != NULL) ? g_source_get_name (source) : "(unnamed)", + result ? "dispatch" : "ignore"); + LOCK_CONTEXT (context); context->in_check_or_prepare--; } @@ -4004,9 +4040,12 @@ g_main_context_iterate (GMainContext *context, gboolean some_ready; gint nfds, allocated_nfds; GPollFD *fds = NULL; + gint64 begin_time_nsec G_GNUC_UNUSED; UNLOCK_CONTEXT (context); + begin_time_nsec = G_TRACE_CURRENT_TIME; + if (!g_main_context_acquire (context)) { gboolean got_ownership; @@ -4061,6 +4100,10 @@ g_main_context_iterate (GMainContext *context, g_main_context_release (context); + g_trace_mark (begin_time_nsec, G_TRACE_CURRENT_TIME - begin_time_nsec, + "GLib", "g_main_context_iterate", + "Context %p, %s ⇒ %s", context, block ? "blocking" : "non-blocking", some_ready ? "dispatched" : "nothing"); + LOCK_CONTEXT (context); return some_ready; From 6f281ce2e582e05f93465ce7d786b060a133f5f8 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Thu, 25 Jun 2020 22:26:15 +0100 Subject: [PATCH 3/5] gtask: Include task name in complete_in_idle_cb source name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `complete_in_idle_cb()` shows up in a lot of sysprof traces, so it’s quite useful to include the most specific contextual information we can in it. Signed-off-by: Philip Withnall --- gio/gtask.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/gio/gtask.c b/gio/gtask.c index e2877dcd9..fc992c7f9 100644 --- a/gio/gtask.c +++ b/gio/gtask.c @@ -1241,6 +1241,7 @@ g_task_return (GTask *task, GTaskReturnType type) { GSource *source; + gchar *source_name = NULL; if (type != G_TASK_RETURN_FROM_THREAD) task->ever_returned = TRUE; @@ -1289,7 +1290,10 @@ g_task_return (GTask *task, /* Otherwise, complete in the next iteration */ source = g_idle_source_new (); - g_source_set_name (source, "[gio] complete_in_idle_cb"); + source_name = g_strdup_printf ("[gio] %s complete_in_idle_cb", + (task->name != NULL) ? task->name : "(unnamed)"); + g_source_set_name (source, source_name); + g_free (source_name); g_task_attach_source (task, source, complete_in_idle_cb); g_source_unref (source); } From 7cd67c935f2999da1428d9554695b3862ee82802 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Thu, 25 Jun 2020 22:27:10 +0100 Subject: [PATCH 4/5] gspawn: Add sysprof trace support for spawning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use this to replace the much-hated `g_debug()` which told people that `posix_spawn()` (the fast path) wasn’t being used for various reasons. If people want to make their process spawning faster now, they’ll have to use a profiling tool like sysprof to check their program’s performance. Shocking. I think I was wrong to put this `g_debug()` in there in the first place — it hasn’t served its purpose of making people speed up their spawn paths to use `posix_spawn()`, it’s only cluttered up logs and frustrated people. Signed-off-by: Philip Withnall --- glib/gspawn.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/glib/gspawn.c b/glib/gspawn.c index e5f1413ed..80ef669f8 100644 --- a/glib/gspawn.c +++ b/glib/gspawn.c @@ -54,6 +54,7 @@ #include "gspawn.h" #include "gspawn-private.h" #include "gthread.h" +#include "gtrace-private.h" #include "glib/gstdio.h" #include "genviron.h" @@ -1760,7 +1761,10 @@ fork_exec_with_fds (gboolean intermediate_child, if (!intermediate_child && working_directory == NULL && !close_descriptors && !search_path_from_envp && child_setup == NULL) { - g_debug ("Launching with posix_spawn"); + g_trace_mark (G_TRACE_CURRENT_TIME, 0, + "GLib", "posix_spawn", + "%s", argv[0]); + status = do_posix_spawn (argv, envp, search_path, @@ -1796,12 +1800,14 @@ fork_exec_with_fds (gboolean intermediate_child, } else { - g_debug ("posix_spawn avoided %s%s%s%s%s", - !intermediate_child ? "" : "(automatic reaping requested) ", - working_directory == NULL ? "" : "(workdir specified) ", - !close_descriptors ? "" : "(fd close requested) ", - !search_path_from_envp ? "" : "(using envp for search path) ", - child_setup == NULL ? "" : "(child_setup specified) "); + g_trace_mark (G_TRACE_CURRENT_TIME, 0, + "GLib", "fork", + "posix_spawn avoided %s%s%s%s%s", + !intermediate_child ? "" : "(automatic reaping requested) ", + working_directory == NULL ? "" : "(workdir specified) ", + !close_descriptors ? "" : "(fd close requested) ", + !search_path_from_envp ? "" : "(using envp for search path) ", + child_setup == NULL ? "" : "(child_setup specified) "); } #endif /* POSIX_SPAWN_AVAILABLE */ From b08bd04abe0d031fb7baa4ad2147ebe07c4a7521 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Thu, 25 Jun 2020 23:36:08 +0100 Subject: [PATCH 5/5] gtask: Improve task names used internally within GLib And improve them externally, where not otherwise set, by setting them from the function name passed to `g_task_set_source_tag()`, if called by third party code. This should make profiling and debug output from GLib more useful. Signed-off-by: Philip Withnall --- gio/gasyncinitable.c | 1 + gio/gdbusinterfaceskeleton.c | 1 + gio/gdbusprivate.c | 2 ++ gio/gdbusproxy.c | 3 +++ gio/gresolver.c | 3 +++ gio/gtask.c | 5 +++-- gio/gtask.h | 8 ++++++++ gio/gthreadedresolver.c | 7 +++++++ gio/gtlsdatabase.c | 4 ++++ gio/gunixmount.c | 8 +++++--- gio/gunixvolume.c | 8 +++++--- 11 files changed, 42 insertions(+), 8 deletions(-) diff --git a/gio/gasyncinitable.c b/gio/gasyncinitable.c index 8936f98b2..6af650688 100644 --- a/gio/gasyncinitable.c +++ b/gio/gasyncinitable.c @@ -87,6 +87,7 @@ * GTask *task; * * task = g_task_new (initable, cancellable, callback, user_data); + * g_task_set_name (task, G_STRFUNC); * * switch (self->priv->state) * { diff --git a/gio/gdbusinterfaceskeleton.c b/gio/gdbusinterfaceskeleton.c index 4a06516c1..a0125c541 100644 --- a/gio/gdbusinterfaceskeleton.c +++ b/gio/gdbusinterfaceskeleton.c @@ -632,6 +632,7 @@ g_dbus_interface_method_dispatch_helper (GDBusInterfaceSkeleton *interface task = g_task_new (interface, NULL, NULL, NULL); g_task_set_source_tag (task, g_dbus_interface_method_dispatch_helper); + g_task_set_name (task, "[gio] D-Bus interface method dispatch"); g_task_set_task_data (task, data, (GDestroyNotify) dispatch_data_unref); g_task_run_in_thread (task, dispatch_in_thread_func); g_object_unref (task); diff --git a/gio/gdbusprivate.c b/gio/gdbusprivate.c index 8526f6925..5c980b40b 100644 --- a/gio/gdbusprivate.c +++ b/gio/gdbusprivate.c @@ -183,6 +183,7 @@ _g_socket_read_with_control_messages (GSocket *socket, task = g_task_new (socket, cancellable, callback, user_data); g_task_set_source_tag (task, _g_socket_read_with_control_messages); + g_task_set_name (task, "[gio] D-Bus read"); g_task_set_task_data (task, data, (GDestroyNotify) read_with_control_data_free); if (g_socket_condition_check (socket, G_IO_IN)) @@ -1123,6 +1124,7 @@ write_message_async (GDBusWorker *worker, { data->task = g_task_new (NULL, NULL, callback, user_data); g_task_set_source_tag (data->task, write_message_async); + g_task_set_name (data->task, "[gio] D-Bus write message"); data->total_written = 0; write_message_continue_writing (data); } diff --git a/gio/gdbusproxy.c b/gio/gdbusproxy.c index 4c682978d..45fa99a17 100644 --- a/gio/gdbusproxy.c +++ b/gio/gdbusproxy.c @@ -1631,6 +1631,7 @@ async_initable_init_second_async (GAsyncInitable *initable, task = g_task_new (proxy, cancellable, callback, user_data); g_task_set_source_tag (task, async_initable_init_second_async); + g_task_set_name (task, "[gio] D-Bus proxy init"); g_task_set_priority (task, io_priority); /* Check name ownership asynchronously - possibly also start the service */ @@ -1802,6 +1803,7 @@ async_initable_init_async (GAsyncInitable *initable, task = g_task_new (proxy, cancellable, callback, user_data); g_task_set_source_tag (task, async_initable_init_async); + g_task_set_name (task, "[gio] D-Bus proxy init"); g_task_set_priority (task, io_priority); if (proxy->priv->bus_type != G_BUS_TYPE_NONE) @@ -2649,6 +2651,7 @@ g_dbus_proxy_call_internal (GDBusProxy *proxy, my_callback = (GAsyncReadyCallback) reply_cb; task = g_task_new (proxy, cancellable, callback, user_data); g_task_set_source_tag (task, g_dbus_proxy_call_internal); + g_task_set_name (task, "[gio] D-Bus proxy call"); } else { diff --git a/gio/gresolver.c b/gio/gresolver.c index 651e7d0ef..cd5445a65 100644 --- a/gio/gresolver.c +++ b/gio/gresolver.c @@ -576,6 +576,7 @@ lookup_by_name_async_real (GResolver *resolver, task = g_task_new (resolver, cancellable, callback, user_data); g_task_set_source_tag (task, lookup_by_name_async_real); + g_task_set_name (task, "[gio] resolver lookup"); if (addrs) g_task_return_pointer (task, addrs, (GDestroyNotify) g_resolver_free_addresses); else @@ -595,6 +596,7 @@ lookup_by_name_async_real (GResolver *resolver, _("Invalid hostname")); task = g_task_new (resolver, cancellable, callback, user_data); g_task_set_source_tag (task, lookup_by_name_async_real); + g_task_set_name (task, "[gio] resolver lookup"); g_task_return_error (task, error); g_object_unref (task); return; @@ -613,6 +615,7 @@ lookup_by_name_async_real (GResolver *resolver, _("%s not implemented"), "lookup_by_name_with_flags_async"); task = g_task_new (resolver, cancellable, callback, user_data); g_task_set_source_tag (task, lookup_by_name_async_real); + g_task_set_name (task, "[gio] resolver lookup"); g_task_return_error (task, error); g_object_unref (task); } diff --git a/gio/gtask.c b/gio/gtask.c index fc992c7f9..9a5c14850 100644 --- a/gio/gtask.c +++ b/gio/gtask.c @@ -759,6 +759,7 @@ g_task_report_error (gpointer source_object, task = g_task_new (source_object, NULL, callback, callback_data); g_task_set_source_tag (task, source_tag); + g_task_set_name (task, G_STRFUNC); g_task_return_error (task, error); g_object_unref (task); } @@ -982,8 +983,8 @@ g_task_set_return_on_cancel (GTask *task, * Since: 2.36 */ void -g_task_set_source_tag (GTask *task, - gpointer source_tag) +(g_task_set_source_tag) (GTask *task, + gpointer source_tag) { g_return_if_fail (G_IS_TASK (task)); diff --git a/gio/gtask.h b/gio/gtask.h index 73a31e157..08ed7be72 100644 --- a/gio/gtask.h +++ b/gio/gtask.h @@ -78,6 +78,14 @@ GLIB_AVAILABLE_IN_2_60 void g_task_set_name (GTask *task, const gchar *name); +/* Macro wrapper to set the task name when setting the source tag. */ +#define g_task_set_source_tag(task, tag) G_STMT_START { \ + GTask *_task = (task); \ + (g_task_set_source_tag) (_task, tag); \ + if (g_task_get_name (_task) == NULL) \ + g_task_set_name (_task, G_STRINGIFY (tag)); \ +} G_STMT_END + GLIB_AVAILABLE_IN_2_36 gpointer g_task_get_source_object (GTask *task); GLIB_AVAILABLE_IN_2_36 diff --git a/gio/gthreadedresolver.c b/gio/gthreadedresolver.c index 3486162e5..48435b36f 100644 --- a/gio/gthreadedresolver.c +++ b/gio/gthreadedresolver.c @@ -187,6 +187,7 @@ lookup_by_name (GResolver *resolver, data = lookup_data_new (hostname, AF_UNSPEC); task = g_task_new (resolver, cancellable, NULL, NULL); g_task_set_source_tag (task, lookup_by_name); + g_task_set_name (task, "[gio] resolver lookup"); g_task_set_task_data (task, data, (GDestroyNotify)lookup_data_free); g_task_set_return_on_cancel (task, TRUE); g_task_run_in_thread_sync (task, do_lookup_by_name); @@ -228,6 +229,7 @@ lookup_by_name_with_flags (GResolver *resolver, data = lookup_data_new (hostname, AF_UNSPEC); task = g_task_new (resolver, cancellable, NULL, NULL); g_task_set_source_tag (task, lookup_by_name_with_flags); + g_task_set_name (task, "[gio] resolver lookup"); g_task_set_task_data (task, data, (GDestroyNotify)lookup_data_free); g_task_set_return_on_cancel (task, TRUE); g_task_run_in_thread_sync (task, do_lookup_by_name); @@ -251,6 +253,7 @@ lookup_by_name_with_flags_async (GResolver *resolver, data = lookup_data_new (hostname, flags_to_family (flags)); task = g_task_new (resolver, cancellable, callback, user_data); g_task_set_source_tag (task, lookup_by_name_with_flags_async); + g_task_set_name (task, "[gio] resolver lookup"); g_task_set_task_data (task, data, (GDestroyNotify)lookup_data_free); g_task_set_return_on_cancel (task, TRUE); g_task_run_in_thread (task, do_lookup_by_name); @@ -350,6 +353,7 @@ lookup_by_address (GResolver *resolver, task = g_task_new (resolver, cancellable, NULL, NULL); g_task_set_source_tag (task, lookup_by_address); + g_task_set_name (task, "[gio] resolver lookup"); g_task_set_task_data (task, g_object_ref (address), g_object_unref); g_task_set_return_on_cancel (task, TRUE); g_task_run_in_thread_sync (task, do_lookup_by_address); @@ -370,6 +374,7 @@ lookup_by_address_async (GResolver *resolver, task = g_task_new (resolver, cancellable, callback, user_data); g_task_set_source_tag (task, lookup_by_address_async); + g_task_set_name (task, "[gio] resolver lookup"); g_task_set_task_data (task, g_object_ref (address), g_object_unref); g_task_set_return_on_cancel (task, TRUE); g_task_run_in_thread (task, do_lookup_by_address); @@ -1040,6 +1045,7 @@ lookup_records (GResolver *resolver, task = g_task_new (resolver, cancellable, NULL, NULL); g_task_set_source_tag (task, lookup_records); + g_task_set_name (task, "[gio] resolver lookup records"); lrd = g_slice_new (LookupRecordsData); lrd->rrname = g_strdup (rrname); @@ -1067,6 +1073,7 @@ lookup_records_async (GResolver *resolver, task = g_task_new (resolver, cancellable, callback, user_data); g_task_set_source_tag (task, lookup_records_async); + g_task_set_name (task, "[gio] resolver lookup records"); lrd = g_slice_new (LookupRecordsData); lrd->rrname = g_strdup (rrname); diff --git a/gio/gtlsdatabase.c b/gio/gtlsdatabase.c index 256369da3..9341206f1 100644 --- a/gio/gtlsdatabase.c +++ b/gio/gtlsdatabase.c @@ -186,6 +186,7 @@ g_tls_database_real_verify_chain_async (GTlsDatabase *self, task = g_task_new (self, cancellable, callback, user_data); g_task_set_source_tag (task, g_tls_database_real_verify_chain_async); + g_task_set_name (task, "[gio] verify TLS chain"); g_task_set_task_data (task, args, async_verify_chain_free); g_task_run_in_thread (task, async_verify_chain_thread); g_object_unref (task); @@ -264,6 +265,7 @@ g_tls_database_real_lookup_certificate_for_handle_async (GTlsDatabase task = g_task_new (self, cancellable, callback, user_data); g_task_set_source_tag (task, g_tls_database_real_lookup_certificate_for_handle_async); + g_task_set_name (task, "[gio] lookup TLS certificate"); g_task_set_task_data (task, args, async_lookup_certificate_for_handle_free); g_task_run_in_thread (task, async_lookup_certificate_for_handle_thread); g_object_unref (task); @@ -338,6 +340,7 @@ g_tls_database_real_lookup_certificate_issuer_async (GTlsDatabase *sel task = g_task_new (self, cancellable, callback, user_data); g_task_set_source_tag (task, g_tls_database_real_lookup_certificate_issuer_async); + g_task_set_name (task, "[gio] lookup certificate issuer"); g_task_set_task_data (task, args, async_lookup_certificate_issuer_free); g_task_run_in_thread (task, async_lookup_certificate_issuer_thread); g_object_unref (task); @@ -419,6 +422,7 @@ g_tls_database_real_lookup_certificates_issued_by_async (GTlsDatabase task = g_task_new (self, cancellable, callback, user_data); g_task_set_source_tag (task, g_tls_database_real_lookup_certificates_issued_by_async); + g_task_set_name (task, "[gio] lookup certificates issued by"); g_task_set_task_data (task, args, async_lookup_certificates_issued_by_free); g_task_run_in_thread (task, async_lookup_certificates_issued_by_thread); g_object_unref (task); diff --git a/gio/gunixmount.c b/gio/gunixmount.c index 0a6d7f3bf..acfebffdd 100644 --- a/gio/gunixmount.c +++ b/gio/gunixmount.c @@ -302,7 +302,8 @@ eject_unmount_do (GMount *mount, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, - char **argv) + char **argv, + const gchar *task_name) { GUnixMount *unix_mount = G_UNIX_MOUNT (mount); GTask *task; @@ -310,6 +311,7 @@ eject_unmount_do (GMount *mount, task = g_task_new (mount, cancellable, callback, user_data); g_task_set_source_tag (task, eject_unmount_do); + g_task_set_name (task, task_name); g_task_set_task_data (task, g_strdupv (argv), (GDestroyNotify) g_strfreev); if (unix_mount->volume_monitor != NULL) @@ -337,7 +339,7 @@ g_unix_mount_unmount (GMount *mount, else argv[1] = unix_mount->device_path; - eject_unmount_do (mount, cancellable, callback, user_data, argv); + eject_unmount_do (mount, cancellable, callback, user_data, argv, "[gio] unmount mount"); } static gboolean @@ -363,7 +365,7 @@ g_unix_mount_eject (GMount *mount, else argv[1] = unix_mount->device_path; - eject_unmount_do (mount, cancellable, callback, user_data, argv); + eject_unmount_do (mount, cancellable, callback, user_data, argv, "[gio] eject mount"); } static gboolean diff --git a/gio/gunixvolume.c b/gio/gunixvolume.c index a3768e11d..60ae628a2 100644 --- a/gio/gunixvolume.c +++ b/gio/gunixvolume.c @@ -305,7 +305,8 @@ eject_mount_do (GVolume *volume, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data, - const gchar * const *argv) + const gchar * const *argv, + const gchar *task_name) { GSubprocess *subprocess; GError *error = NULL; @@ -313,6 +314,7 @@ eject_mount_do (GVolume *volume, task = g_task_new (volume, cancellable, callback, user_data); g_task_set_source_tag (task, eject_mount_do); + g_task_set_name (task, task_name); if (g_task_return_error_if_cancelled (task)) { @@ -344,7 +346,7 @@ g_unix_volume_mount (GVolume *volume, else argv[1] = unix_volume->device_path; - eject_mount_do (volume, cancellable, callback, user_data, argv); + eject_mount_do (volume, cancellable, callback, user_data, argv, "[gio] mount volume"); } static gboolean @@ -369,7 +371,7 @@ g_unix_volume_eject (GVolume *volume, argv[1] = unix_volume->device_path; - eject_mount_do (volume, cancellable, callback, user_data, argv); + eject_mount_do (volume, cancellable, callback, user_data, argv, "[gio] eject volume"); } static gboolean