]> git.proxmox.com Git - mirror_frr.git/commitdiff
lib: fix a memory leak in FreeBSD
authorRafael Zalamena <rzalamena@opensourcerouting.org>
Tue, 25 Sep 2018 15:05:53 +0000 (12:05 -0300)
committerRafael Zalamena <rzalamena@opensourcerouting.org>
Wed, 3 Oct 2018 19:32:11 +0000 (16:32 -0300)
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 <rzalamena@opensourcerouting.org>
lib/thread.c

index 2c3db27c7bf556e34dcfc11a71b771c49619ba1e..e811bf88c815539b9f6536c212acd6c91dfd4600 100644 (file)
@@ -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)
 {