valgrind - pthread memory leaks on AIX

Hi all,

I have written a small code just to invoke main and return immediately. When built with libpthread on AIX box, valgrind throws lots of memory leak errors. But when built without libpthread, no issues at all.

Here is the sample run for your look. Any idea where I might be going wrong?

On IBM AIX UNIX 5.1
03:23:36 ~/Arun$ cat dummy.c
int main()
{
        return 0;
}
03:23:36 ~/Arun$ gcc -o dummy dummy.c -Wall
03:23:23 ~/Arun$ valgrind --leak-check=full --show-reachable=yes ./dummy
==473082== Memcheck, a memory error detector.
==473082== Copyright (C) 2002-2008, and GNU GPL'd, by Julian Seward et al.
==473082== Using LibVEX rev 1884, a library for dynamic binary translation.
==473082== Copyright (C) 2004-2008, and GNU GPL'd, by OpenWorks LLP.
==473082== Using valgrind-3.4.1, a dynamic binary instrumentation framework.
==473082== Copyright (C) 2000-2008, and GNU GPL'd, by Julian Seward et al.
==473082== For more details, rerun with: -v
==473082==
==473082==
==473082== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
==473082== malloc/free: in use at exit: 0 bytes in 0 blocks.
==473082== malloc/free: 0 allocs, 0 frees, 0 bytes allocated.
==473082== For counts of detected errors, rerun with: -v
==473082== All heap blocks were freed -- no leaks are possible.

Absolutely no leaks in the above run. But when built with -lpthread, valgrind throws a big list of memory leak for the same dummy.c. See the following.

03:24:50 ~/Arun$ gcc -o dummy dummy.c -Wall -lpthread
03:27:30 ~/Arun$ valgrind --leak-check=full --show-reachable=yes ./dummy
==172006== Memcheck, a memory error detector.
==172006== Copyright (C) 2002-2008, and GNU GPL'd, by Julian Seward et al.
==172006== Using LibVEX rev 1884, a library for dynamic binary translation.
==172006== Copyright (C) 2004-2008, and GNU GPL'd, by OpenWorks LLP.
==172006== Using valgrind-3.4.1, a dynamic binary instrumentation framework.
==172006== Copyright (C) 2000-2008, and GNU GPL'd, by Julian Seward et al.
==172006== For more details, rerun with: -v
==172006==
==172006==
==172006== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 272 from 4)
==172006== malloc/free: in use at exit: 32,260 bytes in 73 blocks.
==172006== malloc/free: 75 allocs, 2 frees, 37,292 bytes allocated.
==172006== For counts of detected errors, rerun with: -v
==172006== searching for pointers to 73 not-freed blocks.
==172006== checked 9,271,124 bytes.
==172006==
==172006== 12 bytes in 1 blocks are still reachable in loss record 1 of 9
==172006==    at 0xD0E2B5B0: malloc (vg_replace_malloc.c:207)
==172006==    by 0xD005276F: _cleanup_push_72_6 (in /usr/lib/libpthread.a(shr_xpg5.o))
==172006==    by 0xD0050E5B: pthread_once (in /usr/lib/libpthread.a(shr_xpg5.o))
==172006==    by 0xD02E7D67: __getpwent_tsd_callback (in /usr/lib/libc.a(shr.o))
==172006==    by 0xD02E7893: _libc_inline_callbacks (in /usr/lib/libc.a(shr.o))
==172006==    by 0xD02E7827: _libc_declare_data_functions (in /usr/lib/libc.a(shr.o))
==172006==    by 0xD006AA4F: _pth_init_libc (in /usr/lib/libpthread.a(shr_xpg5.o))
==172006==    by 0xD004A0FB: __pth_init (in /usr/lib/libpthread.a(shr_xpg5.o))
==172006==    by 0x10000353: call_pth_init (in /proc/172006/object/a.out)
==172006==    by 0x1000026B: __threads_init (in /proc/172006/object/a.out)
==172006==    by 0xD02E6EFF: __modinit (in /usr/lib/libc.a(shr.o))
==172006==    by 0x100001AB: (below main) (in /proc/172006/object/a.out)
==172006==
==172006==
==172006== 56 bytes in 2 blocks are still reachable in loss record 2 of 9
==172006==    at 0xD0E2B5B0: malloc (vg_replace_malloc.c:207)
==172006==    by 0xD0068E7B: pthread_atfork (in /usr/lib/libpthread.a(shr_xpg5.o))
==172006==    by 0xD004A0AB: __pth_init (in /usr/lib/libpthread.a(shr_xpg5.o))
==172006==    by 0x10000353: call_pth_init (in /proc/172006/object/a.out)
==172006==    by 0x1000026B: __threads_init (in /proc/172006/object/a.out)
==172006==    by 0xD02E6EFF: __modinit (in /usr/lib/libc.a(shr.o))
==172006==    by 0x100001AB: (below main) (in /proc/172006/object/a.out)
==172006==
==172006==
==172006== 208 bytes in 1 blocks are still reachable in loss record 3 of 9
==172006==    at 0xD0E2B5B0: malloc (vg_replace_malloc.c:207)
==172006==    by 0xD006C08B: _lib_rwlock_init (in /usr/lib/libpthread.a(shr_xpg5.o))
==172006==    by 0xD0297E5F: _rec_rwlock_init_21_7 (in /usr/lib/libc.a(shr.o))
==172006==    by 0xD029DDEB: _libc_locks_init (in /usr/lib/libc.a(shr.o))
==172006==    by 0xD02975A7: _libc_declare_lock_functions (in /usr/lib/libc.a(shr.o))
==172006==    by 0xD006AA43: _pth_init_libc (in /usr/lib/libpthread.a(shr_xpg5.o))
==172006==    by 0xD004A0FB: __pth_init (in /usr/lib/libpthread.a(shr_xpg5.o))
==172006==    by 0x10000353: call_pth_init (in /proc/172006/object/a.out)
==172006==    by 0x1000026B: __threads_init (in /proc/172006/object/a.out)
==172006==    by 0xD02E6EFF: __modinit (in /usr/lib/libc.a(shr.o))
==172006==    by 0x100001AB: (below main) (in /proc/172006/object/a.out)
==172006==
==172006==
==172006== 1,800 bytes in 1 blocks are still reachable in loss record 4 of 9
==172006==    at 0xD0E2B5B0: malloc (vg_replace_malloc.c:207)
==172006==    by 0xD006962F: _pth_init_key (in /usr/lib/libpthread.a(shr_xpg5.o))
==172006==    by 0xD004A07F: __pth_init (in /usr/lib/libpthread.a(shr_xpg5.o))
==172006==    by 0x10000353: call_pth_init (in /proc/172006/object/a.out)
==172006==    by 0x1000026B: __threads_init (in /proc/172006/object/a.out)
==172006==    by 0xD02E6EFF: __modinit (in /usr/lib/libc.a(shr.o))
==172006==    by 0x100001AB: (below main) (in /proc/172006/object/a.out)
==172006==
==172006==
==172006== 4,096 bytes in 1 blocks are still reachable in loss record 5 of 9
==172006==    at 0xD0E2B5B0: malloc (vg_replace_malloc.c:207)
==172006==    by 0xD00695EB: _pth_init_key (in /usr/lib/libpthread.a(shr_xpg5.o))
==172006==    by 0xD004A07F: __pth_init (in /usr/lib/libpthread.a(shr_xpg5.o))
==172006==    by 0x10000353: call_pth_init (in /proc/172006/object/a.out)
==172006==    by 0x1000026B: __threads_init (in /proc/172006/object/a.out)
==172006==    by 0xD02E6EFF: __modinit (in /usr/lib/libc.a(shr.o))
==172006==    by 0x100001AB: (below main) (in /proc/172006/object/a.out)
==172006==
==172006==
==172006== 5,224 bytes in 1 blocks are still reachable in loss record 6 of 9
==172006==    at 0xD0E2B5B0: malloc (vg_replace_malloc.c:207)
==172006==    by 0xD004BFAF: _alloc_initial_pthread (in /usr/lib/libpthread.a(shr_xpg5.o))
==172006==    by 0xD004A067: __pth_init (in /usr/lib/libpthread.a(shr_xpg5.o))
==172006==    by 0x10000353: call_pth_init (in /proc/172006/object/a.out)
==172006==    by 0x1000026B: __threads_init (in /proc/172006/object/a.out)
==172006==    by 0xD02E6EFF: __modinit (in /usr/lib/libc.a(shr.o))
==172006==    by 0x100001AB: (below main) (in /proc/172006/object/a.out)
==172006==
==172006==
==172006== 5,376 bytes in 8 blocks are still reachable in loss record 7 of 9
==172006==    at 0xD0E2B5B0: malloc (vg_replace_malloc.c:207)
==172006==    by 0xD0049DDF: __pth_init (in /usr/lib/libpthread.a(shr_xpg5.o))
==172006==    by 0x10000353: call_pth_init (in /proc/172006/object/a.out)
==172006==    by 0x1000026B: __threads_init (in /proc/172006/object/a.out)
==172006==    by 0xD02E6EFF: __modinit (in /usr/lib/libc.a(shr.o))
==172006==    by 0x100001AB: (below main) (in /proc/172006/object/a.out)
==172006==
==172006==
==172006== 7,296 bytes in 57 blocks are still reachable in loss record 8 of 9
==172006==    at 0xD0E2B5B0: malloc (vg_replace_malloc.c:207)
==172006==    by 0xD0047F73: _lib_spinlock_create (in /usr/lib/libpthread.a(shr_xpg5.o))
==172006==    by 0xD029DE13: _libc_locks_init (in /usr/lib/libc.a(shr.o))
==172006==    by 0xD02975A7: _libc_declare_lock_functions (in /usr/lib/libc.a(shr.o))
==172006==    by 0xD006AA43: _pth_init_libc (in /usr/lib/libpthread.a(shr_xpg5.o))
==172006==    by 0xD004A0FB: __pth_init (in /usr/lib/libpthread.a(shr_xpg5.o))
==172006==    by 0x10000353: call_pth_init (in /proc/172006/object/a.out)
==172006==    by 0x1000026B: __threads_init (in /proc/172006/object/a.out)
==172006==    by 0xD02E6EFF: __modinit (in /usr/lib/libc.a(shr.o))
==172006==    by 0x100001AB: (below main) (in /proc/172006/object/a.out)
==172006==
==172006==
==172006== 8,192 bytes in 1 blocks are still reachable in loss record 9 of 9
==172006==    at 0xD0E2B5B0: malloc (vg_replace_malloc.c:207)
==172006==    by 0xD005B847: _vp_create_locked (in /usr/lib/libpthread.a(shr_xpg5.o))
==172006==    by 0xD005BAEF: _vp_create (in /usr/lib/libpthread.a(shr_xpg5.o))
==172006==    by 0xD004C1CF: _alloc_initial_pthread (in /usr/lib/libpthread.a(shr_xpg5.o))
==172006==    by 0xD004A067: __pth_init (in /usr/lib/libpthread.a(shr_xpg5.o))
==172006==    by 0x10000353: call_pth_init (in /proc/172006/object/a.out)
==172006==    by 0x1000026B: __threads_init (in /proc/172006/object/a.out)
==172006==    by 0xD02E6EFF: __modinit (in /usr/lib/libc.a(shr.o))
==172006==    by 0x100001AB: (below main) (in /proc/172006/object/a.out)
==172006==
==172006== LEAK SUMMARY:
==172006==    definitely lost: 0 bytes in 0 blocks.
==172006==      possibly lost: 0 bytes in 0 blocks.
==172006==    still reachable: 32,260 bytes in 73 blocks.
==172006==         suppressed: 0 bytes in 0 blocks.
03:27:38 ~/Arun$

What is going wrong?! Same is the case with any multithreaded application that I wrote on this AIX box!

It looks like the pthread code (library) initializing.

And according to the summary, all allocations are still reachable (if I am reading this right).

My guess is that they are not free()d on exit, and that is what valgrind looks for.

Do you see a continual leaks or just these malloc()s and that is it? (Obviously in your "real" code.)

I don't see a continuous leak.

No 'definitely lost' memory. The leak is always reachable.

The memory leaked (reachable) always remains constant, immaterial of the number of threads created and destroyed (either by joining or by detached state).

The same code leaks 0 reachable memory on Linux. Could this be because of the way AIX libc handles the allocation and deallocation of thread resources? Weird, though :slight_smile:

To be honest... I do not know. I tried to get valgrind to build on 5.3 and it failed (and I immediately threw in the towel as AIX was not a "supported" platform).

But, I think the no-code example you have should serve as a baseline for running this tool on AIX. You might also write a small block of code that spins up 1+ threads and optionally allocate some memory in each (and possibly even throw away the reference / pointers) to see how much it changes.

I tend to write system tools - nothing really critical - so I stick with the GNU tools as well. You might consider looking at the VAC tools - they may offer you stronger capabilities in this area. It seems like you *always* lose *something* when you take a tool developed on a platform like Linux or BSD to one of the proprietary Unices.

Just my $.02.