From 76d5339dd8efdedfe3bb96e5cb343e30ab2f3d16 Mon Sep 17 00:00:00 2001 From: Pieter Duchi Date: Thu, 22 Oct 2026 06:12:43 +0200 Subject: [PATCH 1/3] gtk.cfg: g_thread_join releases the thread g_thread_join() is the deallocator of g_thread_new() and g_thread_try_new(), but its function entry also had , so the join was ignored and every joined thread was reported as Memory leak: thread Drop and describe the arguments of g_thread_join(), g_thread_new() and g_thread_try_new(), which had no function entry. --- cfg/gtk.cfg | 36 +++++++++++++++++++++++++++++++++++- test/cfg/gtk.c | 24 ++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/cfg/gtk.cfg b/cfg/gtk.cfg index c7cd4793ad2..53c04688bcc 100644 --- a/cfg/gtk.cfg +++ b/cfg/gtk.cfg @@ -8387,9 +8387,43 @@ false + + + false + + + + + + + + + + + + + + false + + + + + + + + + + + + + - false + + + + + diff --git a/test/cfg/gtk.c b/test/cfg/gtk.c index c28eb483f45..6c6ef26da41 100644 --- a/test/cfg/gtk.c +++ b/test/cfg/gtk.c @@ -777,3 +777,27 @@ void g_idle_add_freed_data_test(void) // TODO cppcheck-suppress deallocuse g_idle_add(source_func_frees_data, data); } + +static gpointer thread_func(gpointer data) +{ + return data; +} + +void g_thread_join_releases_thread_test(void) +{ + // cppcheck-suppress [constVariablePointer, unusedAllocatedMemory] + GThread *thread = g_thread_new("test", thread_func, NULL); + g_thread_join(thread); + + // cppcheck-suppress constVariablePointer + GThread *thread_try = g_thread_try_new("test", thread_func, NULL, NULL); + if (thread_try) + g_thread_join(thread_try); +} + +void g_thread_not_joined_test(void) +{ + GThread *thread = g_thread_new("test", thread_func, NULL); + (void)thread; + // cppcheck-suppress memleak +} From 648c6e3393effc4964fc2cc726fb7c14e9d31137 Mon Sep 17 00:00:00 2001 From: Pieter Duchi Date: Fri, 13 Nov 2026 10:06:07 +0100 Subject: [PATCH 2/3] gtk.cfg: GThread is a resource, g_thread_join's argument is not const Review of the previous commit: - direction="in" on g_thread_join's argument made cppcheck suggest a pointer to const (constVariablePointer/constParameterPointer) for every joined thread, although the call releases the thread and takes a non-const GThread *. - As a group, a thread that is only created and joined or unref'd was reported as unusedAllocatedMemory. Creating a thread has side effects, so the group is a now; a thread that is never joined is reported as resourceLeak. g_thread_unref also gets a entry, which it did not have. --- cfg/gtk.cfg | 15 ++++++++++++--- test/cfg/gtk.c | 25 ++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/cfg/gtk.cfg b/cfg/gtk.cfg index 53c04688bcc..c8f994c9241 100644 --- a/cfg/gtk.cfg +++ b/cfg/gtk.cfg @@ -336,13 +336,13 @@ - + g_thread_new g_thread_try_new g_thread_ref g_thread_unref g_thread_join - + g_variant_iter_copy g_variant_iter_new @@ -8420,7 +8420,16 @@ false - + + + + + + + + false + + diff --git a/test/cfg/gtk.c b/test/cfg/gtk.c index 6c6ef26da41..175d6198be6 100644 --- a/test/cfg/gtk.c +++ b/test/cfg/gtk.c @@ -785,19 +785,38 @@ static gpointer thread_func(gpointer data) void g_thread_join_releases_thread_test(void) { - // cppcheck-suppress [constVariablePointer, unusedAllocatedMemory] GThread *thread = g_thread_new("test", thread_func, NULL); g_thread_join(thread); - // cppcheck-suppress constVariablePointer GThread *thread_try = g_thread_try_new("test", thread_func, NULL, NULL); if (thread_try) g_thread_join(thread_try); } +// Creating a thread has side effects, so a thread that is only released is +// not unused. +void g_thread_unref_detaches_thread_test(void) +{ + GThread *thread = g_thread_new("test", thread_func, NULL); + g_thread_unref(thread); +} + +void g_thread_join_parameter_test(GThread *thread) +{ + g_thread_join(thread); +} + void g_thread_not_joined_test(void) { GThread *thread = g_thread_new("test", thread_func, NULL); (void)thread; - // cppcheck-suppress memleak + // cppcheck-suppress resourceLeak +} + +void g_thread_joined_twice_test(void) +{ + GThread *thread = g_thread_new("test", thread_func, NULL); + g_thread_join(thread); + // cppcheck-suppress doubleFree + g_thread_join(thread); } From feffd1d9506e1b7ffa2ed5323ec885f25193d41f Mon Sep 17 00:00:00 2001 From: Pieter Duchi Date: Fri, 13 Nov 2026 16:29:49 +0100 Subject: [PATCH 3/3] gtk.cfg: the data of g_thread_new and g_thread_try_new is not const direction="in" on the gpointer data argument made cppcheck suggest a pointer to const (constVariablePointer/constParameterPointer) for the data, although the thread function gets it as a non-const gpointer. --- cfg/gtk.cfg | 4 ++-- test/cfg/gtk.c | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/cfg/gtk.cfg b/cfg/gtk.cfg index c8f994c9241..09ecfed83e6 100644 --- a/cfg/gtk.cfg +++ b/cfg/gtk.cfg @@ -8399,7 +8399,7 @@ - + @@ -8413,7 +8413,7 @@ - + diff --git a/test/cfg/gtk.c b/test/cfg/gtk.c index 175d6198be6..0b1e17e013a 100644 --- a/test/cfg/gtk.c +++ b/test/cfg/gtk.c @@ -806,6 +806,17 @@ void g_thread_join_parameter_test(GThread *thread) g_thread_join(thread); } +// The thread function gets the data as a non-const gpointer. +void g_thread_data_test(int *data) +{ + GThread *thread = g_thread_new("test", thread_func, data); + g_thread_join(thread); + + GThread *thread_try = g_thread_try_new("test", thread_func, data, NULL); + if (thread_try) + g_thread_join(thread_try); +} + void g_thread_not_joined_test(void) { GThread *thread = g_thread_new("test", thread_func, NULL);