diff options
author | Sverker Eriksson <[email protected]> | 2018-04-26 14:50:37 +0200 |
---|---|---|
committer | Sverker Eriksson <[email protected]> | 2018-04-26 14:51:02 +0200 |
commit | c06c51b3cfa04787f53d835b10697eb7bfba844c (patch) | |
tree | 1a16405d168367737aa4d56f361888f0372404f9 | |
parent | 960467ead200635cb935dfd3aa5a5abe38299ca6 (diff) | |
download | otp-c06c51b3cfa04787f53d835b10697eb7bfba844c.tar.gz otp-c06c51b3cfa04787f53d835b10697eb7bfba844c.tar.bz2 otp-c06c51b3cfa04787f53d835b10697eb7bfba844c.zip |
erts: Fix memory leak in lock checker at thread exit
Leak introduced in 865ac3b740d9efa1a0583349929591c757300412.
-rw-r--r-- | erts/emulator/beam/erl_lock_check.c | 41 |
1 files changed, 26 insertions, 15 deletions
diff --git a/erts/emulator/beam/erl_lock_check.c b/erts/emulator/beam/erl_lock_check.c index d66410367b..463ae898a3 100644 --- a/erts/emulator/beam/erl_lock_check.c +++ b/erts/emulator/beam/erl_lock_check.c @@ -217,6 +217,14 @@ typedef struct { static lc_matrix_t tot_lc_matrix; +#define ERTS_LC_FB_CHUNK_SIZE 10 + +typedef struct lc_alloc_chunk_t_ lc_alloc_chunk_t; +struct lc_alloc_chunk_t_ { + lc_alloc_chunk_t* next; + lc_free_block_t array[ERTS_LC_FB_CHUNK_SIZE]; +}; + typedef struct lc_thread_t_ lc_thread_t; struct lc_thread_t_ { char *thread_name; @@ -227,6 +235,7 @@ struct lc_thread_t_ { lc_locked_lock_list_t locked; lc_locked_lock_list_t required; lc_free_block_t *free_blocks; + lc_alloc_chunk_t *chunks; lc_matrix_t matrix; }; @@ -235,14 +244,6 @@ static ethr_tsd_key locks_key; static lc_thread_t *lc_threads = NULL; static ethr_spinlock_t lc_threads_lock; - -#ifdef ERTS_LC_STATIC_ALLOC -#define ERTS_LC_FB_CHUNK_SIZE 10000 -#else -#define ERTS_LC_FB_CHUNK_SIZE 10 -#endif - - static ERTS_INLINE void lc_lock_threads(void) { @@ -268,12 +269,16 @@ static ERTS_INLINE void lc_free(lc_thread_t* thr, lc_locked_lock_t *p) static lc_locked_lock_t *lc_core_alloc(lc_thread_t* thr) { int i; - lc_free_block_t *fbs; - fbs = (lc_free_block_t *) malloc(sizeof(lc_free_block_t) - * ERTS_LC_FB_CHUNK_SIZE); - if (!fbs) { + lc_alloc_chunk_t* chunk; + lc_free_block_t* fbs; + chunk = (lc_alloc_chunk_t*) malloc(sizeof(lc_alloc_chunk_t)); + if (!chunk) { ERTS_INTERNAL_ERROR("Lock checker failed to allocate memory!"); } + chunk->next = thr->chunks; + thr->chunks = chunk; + + fbs = chunk->array; for (i = 1; i < ERTS_LC_FB_CHUNK_SIZE - 1; i++) { #ifdef DEBUG sys_memset((void *) &fbs[i], 0xdf, sizeof(lc_free_block_t)); @@ -321,6 +326,7 @@ create_thread_data(char *thread_name) thr->locked.last = NULL; thr->prev = NULL; thr->free_blocks = NULL; + thr->chunks = NULL; sys_memzero(&thr->matrix, sizeof(thr->matrix)); lc_lock_threads(); @@ -336,7 +342,7 @@ create_thread_data(char *thread_name) static void collect_matrix(lc_matrix_t*); static void -destroy_locked_locks(lc_thread_t *thr) +destroy_thread_data(lc_thread_t *thr) { ASSERT(thr->thread_name); free((void *) thr->thread_name); @@ -359,8 +365,13 @@ destroy_locked_locks(lc_thread_t *thr) lc_unlock_threads(); - free((void *) thr); + while (thr->chunks) { + lc_alloc_chunk_t* free_me = thr->chunks; + thr->chunks = thr->chunks->next; + free(free_me); + } + free((void *) thr); } static ERTS_INLINE lc_thread_t * @@ -615,7 +626,7 @@ thread_exit_handler(void) print_curr_locks(thr); lc_abort(); } - destroy_locked_locks(thr); + destroy_thread_data(thr); /* erts_tsd_set(locks_key, NULL); */ } } |