Merge pull request #3170 from opensourcerouting/60-memleak-fix

6.0: backport memory leak fix
This commit is contained in:
Donald Sharp 2018-10-15 07:43:15 -04:00 committed by GitHub
commit 09fdff5654
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -57,6 +57,7 @@ pthread_key_t thread_current;
pthread_mutex_t masters_mtx = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t masters_mtx = PTHREAD_MUTEX_INITIALIZER;
static struct list *masters; static struct list *masters;
static void thread_free(struct thread_master *master, struct thread *thread);
/* CLI start ---------------------------------------------------------------- */ /* CLI start ---------------------------------------------------------------- */
static unsigned int cpu_record_hash_key(struct cpu_thread_history *a) static unsigned int cpu_record_hash_key(struct cpu_thread_history *a)
@ -537,6 +538,8 @@ static struct thread *thread_trim_head(struct thread_list *list)
/* Move thread to unuse list. */ /* Move thread to unuse list. */
static void thread_add_unuse(struct thread_master *m, struct thread *thread) static void thread_add_unuse(struct thread_master *m, struct thread *thread)
{ {
pthread_mutex_t mtxc = thread->mtx;
assert(m != NULL && thread != NULL); assert(m != NULL && thread != NULL);
assert(thread->next == NULL); assert(thread->next == NULL);
assert(thread->prev == NULL); assert(thread->prev == NULL);
@ -545,10 +548,15 @@ static void thread_add_unuse(struct thread_master *m, struct thread *thread)
memset(thread, 0, sizeof(struct thread)); memset(thread, 0, sizeof(struct thread));
thread->type = THREAD_UNUSED; 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); thread_list_add(&m->unuse, thread);
else return;
XFREE(MTYPE_THREAD, thread); }
thread_free(m, thread);
} }
/* Free all unused thread. */ /* Free all unused thread. */
@ -559,9 +567,8 @@ static void thread_list_free(struct thread_master *m, struct thread_list *list)
for (t = list->head; t; t = next) { for (t = list->head; t; t = next) {
next = t->next; next = t->next;
XFREE(MTYPE_THREAD, t); thread_free(m, t);
list->count--; list->count--;
m->alloc--;
} }
} }
@ -575,8 +582,7 @@ static void thread_array_free(struct thread_master *m,
t = thread_array[index]; t = thread_array[index];
if (t) { if (t) {
thread_array[index] = NULL; thread_array[index] = NULL;
XFREE(MTYPE_THREAD, t); thread_free(m, t);
m->alloc--;
} }
} }
XFREE(MTYPE_THREAD_POLL, thread_array); XFREE(MTYPE_THREAD_POLL, thread_array);
@ -587,9 +593,8 @@ static void thread_queue_free(struct thread_master *m, struct pqueue *queue)
int i; int i;
for (i = 0; i < queue->size; 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); pqueue_delete(queue);
} }
@ -607,8 +612,7 @@ void thread_master_free_unused(struct thread_master *m)
{ {
struct thread *t; struct thread *t;
while ((t = thread_trim_head(&m->unuse)) != NULL) { while ((t = thread_trim_head(&m->unuse)) != NULL) {
pthread_mutex_destroy(&t->mtx); thread_free(m, t);
XFREE(MTYPE_THREAD, t);
} }
} }
pthread_mutex_unlock(&m->mtx); pthread_mutex_unlock(&m->mtx);
@ -727,6 +731,17 @@ static struct thread *thread_get(struct thread_master *m, uint8_t type,
return thread; 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, static int fd_poll(struct thread_master *m, struct pollfd *pfds, nfds_t pfdsize,
nfds_t count, const struct timeval *timer_wait) nfds_t count, const struct timeval *timer_wait)
{ {
@ -1630,25 +1645,27 @@ void funcname_thread_execute(struct thread_master *m,
int (*func)(struct thread *), void *arg, int val, int (*func)(struct thread *), void *arg, int val,
debugargdef) debugargdef)
{ {
struct cpu_thread_history tmp; struct thread *thread;
struct thread dummy;
memset(&dummy, 0, sizeof(struct thread)); /* Get or allocate new thread to execute. */
pthread_mutex_lock(&m->mtx);
{
thread = thread_get(m, THREAD_EVENT, func, arg, debugargpass);
pthread_mutex_init(&dummy.mtx, NULL); /* Set its event value. */
dummy.type = THREAD_EVENT; pthread_mutex_lock(&thread->mtx);
dummy.add_type = THREAD_EXECUTE; {
dummy.master = NULL; thread->add_type = THREAD_EXECUTE;
dummy.arg = arg; thread->u.val = val;
dummy.u.val = val; thread->ref = &thread;
}
tmp.func = dummy.func = func; pthread_mutex_unlock(&thread->mtx);
tmp.funcname = dummy.funcname = funcname; }
dummy.hist = hash_get(m->cpu_record, &tmp, pthread_mutex_unlock(&m->mtx);
(void *(*)(void *))cpu_record_hash_alloc);
/* Execute thread doing all accounting. */
dummy.schedfrom = schedfrom; thread_call(thread);
dummy.schedfrom_line = fromln;
/* Give back or free thread. */
thread_call(&dummy); thread_add_unuse(m, thread);
} }