mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-28 00:21:52 +03:00
malloc: Fix tcache leak after thread destruction [BZ #22111]
The malloc tcache added in 2.26 will leak all of the elements remaining in the cache and the cache structure itself when a thread exits. The defect is that we do not set tcache_shutting_down early enough, and the thread simply recreates the tcache and places the elements back onto a new tcache which is subsequently lost as the thread exits (unfreed memory). The fix is relatively simple, move the setting of tcache_shutting_down earlier in tcache_thread_freeres. We add a test case which uses mallinfo and some heuristics to look for unaccounted for memory usage between the start and end of a thread start/join loop. It is very reliable at detecting that there is a leak given the number of iterations. Without the fix the test will consume 122MiB of leaked memory.
This commit is contained in:
@ -2916,7 +2916,7 @@ typedef struct tcache_perthread_struct
|
||||
tcache_entry *entries[TCACHE_MAX_BINS];
|
||||
} tcache_perthread_struct;
|
||||
|
||||
static __thread char tcache_shutting_down = 0;
|
||||
static __thread bool tcache_shutting_down = false;
|
||||
static __thread tcache_perthread_struct *tcache = NULL;
|
||||
|
||||
/* Caller must ensure that we know tc_idx is valid and there's room
|
||||
@ -2953,8 +2953,12 @@ tcache_thread_freeres (void)
|
||||
if (!tcache)
|
||||
return;
|
||||
|
||||
/* Disable the tcache and prevent it from being reinitialized. */
|
||||
tcache = NULL;
|
||||
tcache_shutting_down = true;
|
||||
|
||||
/* Free all of the entries and the tcache itself back to the arena
|
||||
heap for coalescing. */
|
||||
for (i = 0; i < TCACHE_MAX_BINS; ++i)
|
||||
{
|
||||
while (tcache_tmp->entries[i])
|
||||
@ -2966,8 +2970,6 @@ tcache_thread_freeres (void)
|
||||
}
|
||||
|
||||
__libc_free (tcache_tmp);
|
||||
|
||||
tcache_shutting_down = 1;
|
||||
}
|
||||
text_set_element (__libc_thread_subfreeres, tcache_thread_freeres);
|
||||
|
||||
|
Reference in New Issue
Block a user