From 24fa6f65efa524d50b64ef404a3ff0f93c8742e5 Mon Sep 17 00:00:00 2001 From: Florian Fischer Date: Fri, 3 Jul 2020 12:22:06 +0200 Subject: [chattymalloc] fix multiple sources of crashes * Don't trace free(0x0) during init (needed if init fails) * Increase the trace window (on a huge maschine 100000 entries was to small) * Don't trace after our thread destructor ran --- chattymalloc.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) (limited to 'chattymalloc.c') diff --git a/chattymalloc.c b/chattymalloc.c index 4696700..fbea7dd 100644 --- a/chattymalloc.c +++ b/chattymalloc.c @@ -39,7 +39,7 @@ along with chattymalloc. If not, see . #define BOOTSTRAP_MEMORY_SIZE 4096 #define GROWTH_THRESHOLD 4096 -#define GROWTH_ENTRIES 100000 +#define GROWTH_ENTRIES 1000000 // flag to stop recursion during bootstrap static int initializing = 0; @@ -62,7 +62,11 @@ static volatile uint64_t total_entries = 0; static pthread_cond_t growing; static pthread_mutex_t growth_mutex; -static __thread pid_t tid = 0; +// tid can be in a tri-state +// -1 : means not initialized yet +// 0 : means after the thread destructor ran +// > 1 : the tid of the alive thread +static __thread pid_t tid = -1; // thread specific key to register a destructor static pthread_key_t tls_key; @@ -152,8 +156,16 @@ static void grow_trace() { } static void write_trace(char func, void *ptr, size_t size, size_t var_arg) { - if (unlikely(tid == 0)) { + // Copy tid on the stack to prevent the compiler from using multiple expensive tls reads + pid_t ltid = tid; + + if (unlikely(ltid == 0)) { + return; + } + + if (unlikely(ltid == -1)) { init_thread(); + ltid = tid; } uint64_t idx = __atomic_fetch_add(&next_entry, 1, __ATOMIC_SEQ_CST); @@ -170,7 +182,7 @@ static void write_trace(char func, void *ptr, size_t size, size_t var_arg) { volatile trace_t *trace = &out[(idx / GROWTH_ENTRIES) % 2][idx]; - trace->tid = tid; + trace->tid = ltid; trace->func = func; trace->ptr = ptr; trace->size = size; @@ -179,6 +191,8 @@ static void write_trace(char func, void *ptr, size_t size, size_t var_arg) { static void log_thread_termination(void *key __attribute__((unused))) { write_trace(THREAD_TERMINATION, NULL, 0, 0); + /* Don't write any traces after thread ressources are deallocated */ + tid = 0; } static void trim_trace() { @@ -273,7 +287,12 @@ void *malloc(size_t size) { } void free(void *ptr) { - // something wrong if we call free before one of the allocators! + // This is needed if we fail during init for example when our trace file can't be opened + if (unlikely(initializing) && ptr == 0) { + return; + } + + // something is fishy if we call free before one of the allocating functions! if (unlikely(next_malloc == NULL)) { init(); } -- cgit v1.2.3