From f6caeb6d1abe94926a49fde6ffc1d4254b308b2a Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Thu, 6 Dec 2018 15:16:33 +0000 Subject: [PATCH 1/2] gthread: Add g_private_set_alloc0() internal convenience API This is a wrapper around g_private_set() which allocates the desired amount of memory for the caller and calls g_private_set() on it. This is intended to make it easier to suppress Valgrind warnings about leaked memory, since g_private_set() is typically used to make one-time per-thread allocations. We can now just add a blanket suppression rule for any allocations inside g_private_set_alloc0(). Signed-off-by: Philip Withnall --- glib.supp | 9 +++++++++ glib/gcharset.c | 6 ++---- glib/gconvert.c | 6 ++---- glib/gmain.c | 8 +++----- glib/gslice.c | 4 ++-- glib/gthread.c | 27 +++++++++++++++++++++++++++ glib/gthreadprivate.h | 3 +++ 7 files changed, 48 insertions(+), 15 deletions(-) diff --git a/glib.supp b/glib.supp index c8b184e5c..7b8478803 100644 --- a/glib.supp +++ b/glib.supp @@ -656,4 +656,13 @@ ... fun:g_dbus_error_register_error_domain fun:g_dbus_error_quark +} + +# Thread-private data allocated once per thread +{ + g_private_set_alloc0 + Memcheck:Leak + fun:malloc + ... + fun:g_private_set_alloc0 } \ No newline at end of file diff --git a/glib/gcharset.c b/glib/gcharset.c index a97b33a03..8f4f03946 100644 --- a/glib/gcharset.c +++ b/glib/gcharset.c @@ -27,6 +27,7 @@ #include "gmessages.h" #include "gstrfuncs.h" #include "gthread.h" +#include "gthreadprivate.h" #ifdef G_OS_WIN32 #include "gwin32.h" #endif @@ -187,10 +188,7 @@ g_get_charset (const char **charset) const gchar *raw; if (!cache) - { - cache = g_new0 (GCharsetCache, 1); - g_private_set (&cache_private, cache); - } + cache = g_private_set_alloc0 (&cache_private, sizeof (GCharsetCache)); G_LOCK (aliases); raw = _g_locale_charset_raw (); diff --git a/glib/gconvert.c b/glib/gconvert.c index 3f6621b2a..707867951 100644 --- a/glib/gconvert.c +++ b/glib/gconvert.c @@ -46,6 +46,7 @@ #include "gstrfuncs.h" #include "gtestutils.h" #include "gthread.h" +#include "gthreadprivate.h" #include "gunicode.h" #include "gfileutils.h" @@ -1131,10 +1132,7 @@ g_get_filename_charsets (const gchar ***filename_charsets) const gchar *charset; if (!cache) - { - cache = g_new0 (GFilenameCharsetCache, 1); - g_private_set (&cache_private, cache); - } + cache = g_private_set_alloc0 (&cache_private, sizeof (GFilenameCharsetCache)); g_get_charset (&charset); diff --git a/glib/gmain.c b/glib/gmain.c index c24690e44..83e398cfa 100644 --- a/glib/gmain.c +++ b/glib/gmain.c @@ -87,6 +87,7 @@ #include "gqueue.h" #include "gstrfuncs.h" #include "gtestutils.h" +#include "gthreadprivate.h" #ifdef G_OS_WIN32 #include "gwin32.h" @@ -2828,7 +2829,7 @@ g_get_monotonic_time (void) static void g_main_dispatch_free (gpointer dispatch) { - g_slice_free (GMainDispatch, dispatch); + g_free (dispatch); } /* Running the main loop */ @@ -2842,10 +2843,7 @@ get_dispatch (void) dispatch = g_private_get (&depth_private); if (!dispatch) - { - dispatch = g_slice_new0 (GMainDispatch); - g_private_set (&depth_private, dispatch); - } + dispatch = g_private_set_alloc0 (&depth_private, sizeof (GMainDispatch)); return dispatch; } diff --git a/glib/gslice.c b/glib/gslice.c index d1b1fc639..86e76cec0 100644 --- a/glib/gslice.c +++ b/glib/gslice.c @@ -45,6 +45,7 @@ #include "gtrashstack.h" #include "gtestutils.h" #include "gthread.h" +#include "gthreadprivate.h" #include "glib_trace.h" #include "gprintf.h" @@ -515,10 +516,9 @@ thread_memory_from_self (void) g_mutex_unlock (&init_mutex); n_magazines = MAX_SLAB_INDEX (allocator); - tmem = g_malloc0 (sizeof (ThreadMemory) + sizeof (Magazine) * 2 * n_magazines); + tmem = g_private_set_alloc0 (&private_thread_memory, sizeof (ThreadMemory) + sizeof (Magazine) * 2 * n_magazines); tmem->magazine1 = (Magazine*) (tmem + 1); tmem->magazine2 = &tmem->magazine1[n_magazines]; - g_private_set (&private_thread_memory, tmem); } return tmem; } diff --git a/glib/gthread.c b/glib/gthread.c index 69010f978..2b7be91dd 100644 --- a/glib/gthread.c +++ b/glib/gthread.c @@ -517,6 +517,33 @@ static GPrivate g_thread_specific_private = G_PRIVATE_INIT (g_thread_cleanup G_LOCK_DEFINE_STATIC (g_thread_new); +/* + * g_private_set_alloc0: + * @key: a #GPrivate + * @size: size of the allocation, in bytes + * + * Sets the thread local variable @key to have a newly-allocated and zero-filled + * value of given @size, and returns a pointer to that memory. Allocations made + * using this API will be suppressed in valgrind: it is intended to be used for + * one-time allocations which are known to be leaked, such as those for + * per-thread initialisation data. Otherwise, this function behaves the same as + * g_private_set(). + * + * Returns: (transfer full): new thread-local heap allocation of size @size + * Since: 2.60 + */ +/*< private >*/ +gpointer +g_private_set_alloc0 (GPrivate *key, + gsize size) +{ + gpointer allocated = g_malloc0 (size); + + g_private_set (key, allocated); + + return g_steal_pointer (&allocated); +} + /* GOnce {{{1 ------------------------------------------------------------- */ /** diff --git a/glib/gthreadprivate.h b/glib/gthreadprivate.h index 2cf8bdc00..75bb3cbf2 100644 --- a/glib/gthreadprivate.h +++ b/glib/gthreadprivate.h @@ -56,4 +56,7 @@ GThread * g_thread_new_internal (const gchar *name, gpointer g_thread_proxy (gpointer thread); +gpointer g_private_set_alloc0 (GPrivate *key, + gsize size); + #endif /* __G_THREADPRIVATE_H__ */ From 140c2a225a50523eee0f70995dc683b48e2528fb Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Thu, 6 Dec 2018 15:24:42 +0000 Subject: [PATCH 2/2] glib.supp: Add a suppression for GMainContext default stacks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since this uses a private GQueue, we can’t suppress this by using g_private_set_alloc0(). Signed-off-by: Philip Withnall --- glib.supp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/glib.supp b/glib.supp index 7b8478803..ac753d3b0 100644 --- a/glib.supp +++ b/glib.supp @@ -665,4 +665,14 @@ fun:malloc ... fun:g_private_set_alloc0 +} + +# Thread-private GMainContext stack +{ + g_main_context_push_thread_default + Memcheck:Leak + fun:malloc + ... + fun:g_queue_new + fun:g_main_context_push_thread_default } \ No newline at end of file