ConfD User Community

Memory Leak Observed

Hi All,
I am doing analysis on memory leak for the create/delete configuration and get-config opertation.
What I observed is when deleting the interface in node, the below memory leak was observed and 67 bytes of memory are lost when committed the deletion of a single interface.
From the call stack below, it goes to confd lib call stack ,
Could you please give your comments why this leak was observed and how to
resolve this memory leak?

==18304== 67 bytes in 1 blocks are definitely lost in loss record 20,085 of 34,746
==18304== at 0x4005C18: malloc (vg_replace_malloc.c:270)
==18304== by 0x43ADBA5: wrapped_malloc (WrappedAllocator.c++:190)
==18304== by 0x9724A3E: malloc (MallocLeakDetect.c++:112)
==18304== by 0x44A4F3B7: strdup (strdup.c:42)
==18304== by 0x4034BEF: _confd_vset_error (confd_lib.c:3231)
==18304== by 0x40388BD: confd_trans_seterr (confd_lib.c:5834)
==18304== by 0x966EF35: ConfDInterface::RemoveElement(confd_trans_ctx*, confd_hkeypath*, session&) (ConfDInterface.c++:2416)

Hi All,
Could you please help on the query which I raised.
Do we need to free anything from our side other than confd perspective when call hits confd_trans_seterr ?

I assume transaction for which you have set the error (via confd_trans_seterr()) was not finished/terminated properly.

(which is the point where would be released, or on repeated call to confd_trans_seterr())

if you have new transaction opened explicitly by yourself, you may be missing e.g. maapi_finish_trans()

if this is for some callback registered with confd, you may be terminating app during the running transaction and miss some “destructor” work that would close/finish the transaction from app’s point of view…

So question is what leads to your scenario -> do you have some sockets closed, network connectivity interruptions, app crash, etc.?

Hi Joseph,
The scenario is,
I have created one interface and delete the same interface. Then I collected the valgrind logs and seen some approx 67 bytes were lost. Basically I am checking for memory leak for create/delete/GET operation
There is no crash or socket closed issue observed. Only the leak is the issue here.
And the call stack is below for the scenario,

==18304== 67 bytes in 1 blocks are definitely lost in loss record 20,085 of 34,746
==18304== at 0x4005C18: malloc (vg_replace_malloc.c:270)
==18304== by 0x43ADBA5: wrapped_malloc (WrappedAllocator.c++:190)
==18304== by 0x9724A3E: malloc (MallocLeakDetect.c++:112)
==18304== by 0x44A4F3B7: strdup (strdup.c:42)
==18304== by 0x4034BEF: _confd_vset_error (confd_lib.c:3231)
==18304== by 0x40388BD: confd_trans_seterr (confd_lib.c:5834)
==18304== by 0x966EF35: ConfDInterface::RemoveElement(confd_trans_ctx*, confd_hkeypath*, session&) (ConfDInterface.c++:2416)

My current understanding is:

  • valgrind shows that call to confd_trans_seterr() has been done in your code
  • this supposedly allocates some memory
  • this memory is freed either on:
    • next call to confd_trans_seterr()
      (this of course means it allocates new memory for new call, but it also means that there is no growing leak)
    • (X) when transaction is closed/terminated properly
      (user finishes norhtbound session / or, if you opened it in your app the code finishes transaction via finish call…

valgrind complains that there is “mem-leak”, which means that app was terminated (as valgrind prints leak info on app termination) before (X) happened.
(confd-lib never got chance (or reason) to clear memory properly)

Hi Joseph,
I will try to summarize the leak and when it hits. Based on that please give your comments.

Usecase Steps :

  1. Create one Interface and delete the same interface
  2. The confd trace logs shows interface got deleted and transaction was finished.

2020-11-05 23:24:32:084 TRACE CALL data delete(thandle=39,/interfaces/interface{itf.0})2020-11-05 23:24:32:084 --> CONFD_ACCUMULATE
2020-11-05 23:24:32:084 TRACE CALL trans prepare(thandle=39)2020-11-05 23:24:32:512 --> CONFD_OK
2020-11-05 23:24:32:515 TRACE CALL trans commit(thandle=39)2020-11-05 23:24:32:516 --> CONFD_OK
2020-11-05 23:24:32:516 TRACE CALL trans finish(thandle=39)2020-11-05 23:24:32:517 --> CONFD_OK

  1. Then I killed the process to collect valgrind logs, there I have seen the leak of 67 bytes.

==18304== 67 bytes in 1 blocks are definitely lost in loss record 20,085 of 34,746
==18304== at 0x4005C18: malloc (vg_replace_malloc.c:270)
==18304== by 0x43ADBA5: wrapped_malloc (WrappedAllocator.c++:190)
==18304== by 0x9724A3E: malloc (MallocLeakDetect.c++:112)
==18304== by 0x44A4F3B7: strdup (strdup.c:42)
==18304== by 0x4034BEF: _confd_vset_error (confd_lib.c:3231)
==18304== by 0x40388BD: confd_trans_seterr (confd_lib.c:5834)
==18304== by 0x966EF35: ConfDInterface::RemoveElement(confd_trans_ctx*, confd_hkeypath*, session&) (ConfDInterface.c++:2416)

From the ConfD UG (that has been quoted many times before):

When debugging application memory leaks with a tool like valgrind, it is often necessary to rebuild libconfd from source, since the default build uses a “pool allocator” that makes the stack trace information for memory leaks from valgrind completely misleading for allocations from libconfd. The details of how to do a build that disables the pool allocator are described in the “Application debugging” section of the README in the libconfd source package

…and from the “libconfd source package” README:

When debugging application memory leaks with a tool like ‘valgrind’, and
the stack trace information from ‘valgrind’ indicates that memory
allocated by libconfd has not been freed, it is necessary to rebuild
libconfd from source, since the default build uses a “pool allocator”
that makes the stack trace information for libconfd completely
misleading.

To build a version of libconfd that disables the pool allocator, the
environment variable $NO_FIX_ALLOC must be set to “yes” before building
from a freshly unpacked tar archive - running ‘make clean’ after an
earlier build is not sufficient. I.e. proceed as follows:

  1. Unpack the tar archive.
  2. Do ‘export NO_FIX_ALLOC=yes’ in the shell.
  3. Build as described above.

Note that the libconfd performance may be degraded when the pool
allocator is disabled - i.e. such a build should only be used for
debugging.

1 Like