I created a JOINABLE thread and later canceled it near the end of the program, e.g.
rc2 = pthread_attr_init(&attr);
ERR_IF( rc2 != 0 );
rc2 = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
ERR_IF( rc2 != 0 );
rc2 = pthread_create(&destroy_thread, &attr, destroy_expired_sessions, NULL);
ERR_IF( rc2 != 0 );
...
rc2 = pthread_cancel(destroy_thread);
ERR_IF( rc2 != 0 );
rc2 = pthread_join(destroy_thread, &status);
ERR_IF( rc2 != 0 || (int *)status != PTHREAD_CANCELED);
Yet, there is memory leak with pthread_cancel(), analyzed by valgrind:
==17583== 28 bytes in 1 blocks are still reachable in loss record 1 of 1
==17583== at 0x4006878: malloc (in /m/mls/pkg/trees/2008Q3/ix86-Linux-RHEL5/lib/valgrind/x86-linux/vgpreload_memcheck.so)
==17583== by 0x79FAC1: _dl_map_object_deps (in /lib/ld-2.5.so)
==17583== by 0x7A4A67: dl_open_worker (in /lib/ld-2.5.so)
==17583== by 0x7A0DA5: _dl_catch_error (in /lib/ld-2.5.so)
==17583== by 0x7A43F1: _dl_open (in /lib/ld-2.5.so)
==17583== by 0x8BF2E1: do_dlopen (in /lib/libc-2.5.so)
==17583== by 0x7A0DA5: _dl_catch_error (in /lib/ld-2.5.so)
==17583== by 0x8BF494: __libc_dlopen_mode (in /lib/libc-2.5.so)
==17583== by 0x9527D6: pthread_cancel_init (in /lib/libpthread-2.5.so)
==17583== by 0x94EC1B: pthread_cancel (in /lib/libpthread-2.5.so)
==17583== by 0x80860CF: authDeinit (authAPI.c:1545)
==17583== by 0x807F280: main (test_sessionList.c:124)
==17583==
==17583== LEAK SUMMARY:
==17583== definitely lost: 0 bytes in 0 blocks.
==17583== possibly lost: 0 bytes in 0 blocks.
==17583== still reachable: 28 bytes in 1 blocks.
==17583== suppressed: 0 bytes in 0 blocks.
It seems a defect of the function pthread_cancel() itself. Looks like it malloc()’ed some memory but didn’t free() it later. Is there any way to avoid the memory leak here?
This is how
pthread_cancel()is designed to work. When called, it’ll callpthread_cancel_init()to ensure that several items are dynamically linked (using equivalents todlopen()anddlsym()). Those dynamically linked functions/symbols are intended to be available for the remainder of the process’ lifetime.So this isn’t a leak in the sense that something has been lost track of – rather it’s something loaded and intended to remain alive.
I’d suggest that valgrind be configured to ignore this allocation if possible.