mainloop test leaks a GMainLoop object
To reproduce:
- recent GLib (I used c07f8a70 as a base, with !1905 (merged) applied)
- a recent GNU/Linux system (I used Debian's
unstable
rolling release) - build GLib with gcc AddressSanitizer (
-Db_sanitize=address
in Meson)- I used Debian's gcc 10.2.1-6
- I used UndefinedBehaviourSanitizer too (
-Db_sanitize=address,undefined
) but that probably doesn't matter - clang AddressSanitizer would probably also reproduce this
- if !1905 (merged) has been applied, partially or fully revert commit "tests: Mark tests with AddressSanitizer-detected leaks" to re-expose this leak
- run unit tests, specifically
glib:glib / mainloop
(akaglib/tests/mainloop.c
)
Expected result: no memory is leaked and unreachable on process exit.
Actual result:
==2936774==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x7f4eda04e037 in __interceptor_calloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:154
#1 0x7f4ed992387a in g_malloc0 ../../../../../../home/smcv/src/glib/glib/gmem.c:136
#2 0x7f4ed9923bda in g_malloc0_n ../../../../../../home/smcv/src/glib/glib/gmem.c:368
#3 0x7f4ed9901b9f in g_main_loop_new ../../../../../../home/smcv/src/glib/glib/gmain.c:4224
#4 0x55a0715d7027 in threadf ../../../../../../home/smcv/src/glib/glib/tests/mainloop.c:1632
#5 0x7f4ed99bfc26 in g_thread_proxy ../../../../../../home/smcv/src/glib/glib/gthread.c:826
#6 0x7f4ed9a79fbd in linux_pthread_proxy ../../../../../../home/smcv/src/glib/glib/gthread-posix.c:1259
#7 0x7f4ed8aefea6 in start_thread nptl/pthread_create.c:477
SUMMARY: AddressSanitizer: 16 byte(s) leaked in 1 allocation(s).
This is part of test_mainloop_wait()
, which creates two threads t1
and t2
both running threadf()
in the same main-context. threadf()
creates a 250ms timeout, attaches it to the main-context, and uses a GMainLoop
to wait for the timeout. I do not see any obviously wrong refcounting.
The leak is one of the GMainLoop
structs:
GMainLoop *
g_main_loop_new (GMainContext *context,
gboolean is_running)
{
GMainLoop *loop;
if (!context)
context = g_main_context_default();
g_main_context_ref (context);
loop = g_new0 (GMainLoop, 1); <<< HERE
loop->context = context;
loop->is_running = is_running != FALSE;
loop->ref_count = 1;
TRACE (GLIB_MAIN_LOOP_NEW (loop, context));
return loop;
}
I don't know whether this is a false-positive, a bug in the test or a bug in GMainLoop. I also don't know why one main-loop is leaked but the other is not.
For now, I've marked this test g_test_incomplete()
when running under AddressSanitizer, so that we can run the rest of the test-suite under AddressSanitizer and at least make sure we don't regress.