Description:
From code analysis:
void *_lf_alloc_new(LF_PINS *pins)
{
LF_ALLOCATOR *allocator= (LF_ALLOCATOR *)(pins->pinbox->free_func_arg);
uchar *node;
for (;;)
{
do
{
(1)
node= allocator->top;
_lf_pin(pins, 0, node);
} while (node != allocator->top && LF_BACKOFF);
if (!node)
{
(2)
node= (void *)my_malloc(allocator->element_size, MYF(MY_WME));
if (allocator->constructor)
allocator->constructor(node);
#ifdef MY_LF_EXTRA_DEBUG
if (likely(node != 0))
my_atomic_add32(&allocator->mallocs, 1);
#endif
break;
}
(3)
if (my_atomic_casptr((void **)(char *)&allocator->top,
(void *)&node, anext_node(node)))
break;
}
_lf_unpin(pins, 0);
return node;
}
When the atomic CAS operation from (3) fails, the code loops again in the
for (;;) loop.
In this case, memory allocated in (2) is lost, since 'node' is assigned to
a new value in (1).
This seems to be the root cause of spurious memory leaks such as:
==23899==
==23899== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 3 from 1)
==23899== malloc/free: in use at exit: 48 bytes in 2 blocks.
==23899== malloc/free: 5,483 allocs, 5,481 frees, 66,622,748 bytes allocated.
==23899== For counts of detected errors, rerun with: -v
==23899== searching for pointers to 2 not-freed blocks.
==23899== checked 1,596,840 bytes.
==23899==
==23899== 20 bytes in 1 blocks are definitely lost in loss record 1 of 2
==23899== at 0x4024D5E: malloc (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so)
==23899== by 0x873C90B: my_malloc (my_malloc.c:37)
==23899== by 0x874A9D0: _lf_alloc_new (lf_alloc-pin.c:503)
==23899== by 0x87B2BBB: lf_hash_insert (lf_hash.c:373)
==23899== by 0x87D43CB: find_or_create_file(PFS_thread*, PFS_file_class*, char const*, unsigned) (pfs_instr.cc:802)
==23899== by 0x87E0F23: _ZL30get_thread_file_name_locker_v1j18PSI_file_operationPKcPKv (pfs.cc:1297)
==23899== by 0x82F44BD: _ZL24inline_mysql_file_createjPKcjS0_iii (mysql_file.h:861)
==23899== by 0x82F470F: _ZL15create_pid_filev (mysqld.cc:9547)
==23899== by 0x82F91BE: signal_hand (mysqld.cc:2926)
==23899== by 0x87E138B: pfs_spawn_thread(void*) (pfs.cc:1007)
==23899== by 0x406A174: start_thread (in /lib/libpthread-2.8.so)
==23899== by 0x42BFDAD: clone (in /lib/libc-2.8.so)
==23899==
==23899== LEAK SUMMARY:
==23899== definitely lost: 20 bytes in 1 blocks.
==23899== possibly lost: 0 bytes in 0 blocks.
==23899== still reachable: 0 bytes in 0 blocks.
==23899== suppressed: 28 bytes in 1 blocks.
which was detected in mysql-azalea-perfschema.
How to repeat:
Read the code.
Note that for atomic operations to fail, you need a multi core machine,
when using native atomic operations.
Suggested fix:
Reuse the allocated node instead of allocating a new one in each loop iteration