From: Rafael Zalamena Date: Tue, 25 Sep 2018 15:05:53 +0000 (-0300) Subject: lib: fix a memory leak in FreeBSD X-Git-Tag: frr-7.0.1~311^2~1 X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=6655966d2c2fe7a29ca29af4366fa3e044ad1170;p=mirror_frr.git lib: fix a memory leak in FreeBSD Two important changes: * Centralize the thread teardown procedure; * Save and restore thread mutex context to avoid losing the memory pointer; Signed-off-by: Rafael Zalamena --- diff --git a/lib/thread.c b/lib/thread.c index 2c3db27c7..e811bf88c 100644 --- a/lib/thread.c +++ b/lib/thread.c @@ -58,6 +58,7 @@ pthread_key_t thread_current; pthread_mutex_t masters_mtx = PTHREAD_MUTEX_INITIALIZER; static struct list *masters; +static void thread_free(struct thread_master *master, struct thread *thread); /* CLI start ---------------------------------------------------------------- */ static unsigned int cpu_record_hash_key(struct cpu_thread_history *a) @@ -538,6 +539,8 @@ static struct thread *thread_trim_head(struct thread_list *list) /* Move thread to unuse list. */ static void thread_add_unuse(struct thread_master *m, struct thread *thread) { + pthread_mutex_t mtxc = thread->mtx; + assert(m != NULL && thread != NULL); assert(thread->next == NULL); assert(thread->prev == NULL); @@ -546,10 +549,15 @@ static void thread_add_unuse(struct thread_master *m, struct thread *thread) memset(thread, 0, sizeof(struct thread)); thread->type = THREAD_UNUSED; - if (m->unuse.count < THREAD_UNUSED_DEPTH) + /* Restore the thread mutex context. */ + thread->mtx = mtxc; + + if (m->unuse.count < THREAD_UNUSED_DEPTH) { thread_list_add(&m->unuse, thread); - else - XFREE(MTYPE_THREAD, thread); + return; + } + + thread_free(m, thread); } /* Free all unused thread. */ @@ -560,9 +568,8 @@ static void thread_list_free(struct thread_master *m, struct thread_list *list) for (t = list->head; t; t = next) { next = t->next; - XFREE(MTYPE_THREAD, t); + thread_free(m, t); list->count--; - m->alloc--; } } @@ -576,8 +583,7 @@ static void thread_array_free(struct thread_master *m, t = thread_array[index]; if (t) { thread_array[index] = NULL; - XFREE(MTYPE_THREAD, t); - m->alloc--; + thread_free(m, t); } } XFREE(MTYPE_THREAD_POLL, thread_array); @@ -588,9 +594,8 @@ static void thread_queue_free(struct thread_master *m, struct pqueue *queue) int i; for (i = 0; i < queue->size; i++) - XFREE(MTYPE_THREAD, queue->array[i]); + thread_free(m, queue->array[i]); - m->alloc -= queue->size; pqueue_delete(queue); } @@ -608,8 +613,7 @@ void thread_master_free_unused(struct thread_master *m) { struct thread *t; while ((t = thread_trim_head(&m->unuse)) != NULL) { - pthread_mutex_destroy(&t->mtx); - XFREE(MTYPE_THREAD, t); + thread_free(m, t); } } pthread_mutex_unlock(&m->mtx); @@ -728,6 +732,17 @@ static struct thread *thread_get(struct thread_master *m, uint8_t type, return thread; } +static void thread_free(struct thread_master *master, struct thread *thread) +{ + /* Update statistics. */ + assert(master->alloc > 0); + master->alloc--; + + /* Free allocated resources. */ + pthread_mutex_destroy(&thread->mtx); + XFREE(MTYPE_THREAD, thread); +} + static int fd_poll(struct thread_master *m, struct pollfd *pfds, nfds_t pfdsize, nfds_t count, const struct timeval *timer_wait) {