From bcd1979454cd14087394f0c0a983205f6fbfcaf4 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Fri, 4 Oct 2019 21:06:33 +0200 Subject: [PATCH] Fix memory leaks from timers. --- src/event.c | 40 +++++++++++++++++++++++++++++----------- src/meshlink.c | 2 +- src/net.c | 4 +++- src/protocol.c | 20 ++++++++++++++------ 4 files changed, 47 insertions(+), 19 deletions(-) diff --git a/src/event.c b/src/event.c index 245e39ec..f88112ff 100644 --- a/src/event.c +++ b/src/event.c @@ -129,6 +129,15 @@ void timeout_set(event_loop_t *loop, timeout_t *timeout, struct timeval *tv) { if(!splay_insert_node(&loop->timeouts, &timeout->node)) { abort(); } + + loop->deletion = true; +} + +static void timeout_disable(event_loop_t *loop, timeout_t *timeout) { + splay_unlink_node(&loop->timeouts, &timeout->node); + timeout->tv = (struct timeval) { + 0, 0 + }; } void timeout_del(event_loop_t *loop, timeout_t *timeout) { @@ -136,13 +145,12 @@ void timeout_del(event_loop_t *loop, timeout_t *timeout) { return; } - loop->deletion = true; + if(timerisset(&timeout->tv)) { + timeout_disable(loop, timeout); + } - splay_unlink_node(&loop->timeouts, &timeout->node); - timeout->cb = 0; - timeout->tv = (struct timeval) { - 0, 0 - }; + timeout->cb = NULL; + loop->deletion = true; } static int signal_compare(const signal_t *a, const signal_t *b) { @@ -173,6 +181,16 @@ static void pipe_init(event_loop_t *loop) { } } +static void pipe_exit(event_loop_t *loop) { + io_del(loop, &loop->signalio); + + close(loop->pipefd[0]); + close(loop->pipefd[1]); + + loop->pipefd[0] = -1; + loop->pipefd[1] = -1; +} + void signal_trigger(event_loop_t *loop, signal_t *sig) { uint8_t signum = sig->signum; write(loop->pipefd[1], &signum, 1); @@ -207,6 +225,10 @@ void signal_del(event_loop_t *loop, signal_t *sig) { splay_unlink_node(&loop->signals, &sig->node); sig->cb = NULL; + + if(!loop->signals.count && loop->pipefd[0] != -1) { + pipe_exit(loop); + } } void idle_set(event_loop_t *loop, idle_cb_t cb, void *data) { @@ -218,7 +240,6 @@ bool event_loop_run(event_loop_t *loop, pthread_mutex_t *mutex) { fd_set readable; fd_set writable; - while(loop->running) { gettimeofday(&loop->now, NULL); struct timeval diff, it, *tv = NULL; @@ -228,11 +249,8 @@ bool event_loop_run(event_loop_t *loop, pthread_mutex_t *mutex) { timersub(&timeout->tv, &loop->now, &diff); if(diff.tv_sec < 0) { + timeout_disable(loop, timeout); timeout->cb(loop, timeout->data); - - if(timercmp(&timeout->tv, &loop->now, <)) { - timeout_del(loop, timeout); - } } else { tv = &diff; break; diff --git a/src/meshlink.c b/src/meshlink.c index bee8eee3..a9988855 100644 --- a/src/meshlink.c +++ b/src/meshlink.c @@ -3512,7 +3512,7 @@ void meshlink_set_dev_class_timeouts(meshlink_handle_t *mesh, dev_class_t devcla void handle_network_change(meshlink_handle_t *mesh, bool online) { (void)online; - if(!mesh->connections) { + if(!mesh->connections || !mesh->loop.running) { return; } diff --git a/src/net.c b/src/net.c index 9dd42dd5..c7c6723c 100644 --- a/src/net.c +++ b/src/net.c @@ -706,15 +706,17 @@ int main_loop(meshlink_handle_t *mesh) { mesh->datafromapp.signum = 0; signal_add(&(mesh->loop), &(mesh->datafromapp), (signal_cb_t)meshlink_send_from_queue, mesh, mesh->datafromapp.signum); - if(!event_loop_run(&(mesh->loop), &(mesh->mesh_mutex))) { + if(!event_loop_run(&mesh->loop, &mesh->mesh_mutex)) { logger(mesh, MESHLINK_ERROR, "Error while waiting for input: %s", strerror(errno)); abort(); + signal_del(&mesh->loop, &mesh->datafromapp); timeout_del(&mesh->loop, &mesh->periodictimer); timeout_del(&mesh->loop, &mesh->pingtimer); return 1; } + signal_del(&mesh->loop, &mesh->datafromapp); timeout_del(&mesh->loop, &mesh->periodictimer); timeout_del(&mesh->loop, &mesh->pingtimer); diff --git a/src/protocol.c b/src/protocol.c index fd180f4f..92418f17 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -200,10 +200,11 @@ static void age_past_requests(event_loop_t *loop, void *data) { logger(mesh, MESHLINK_DEBUG, "Aging past requests: deleted %d, left %d", deleted, left); } - if(left) + if(left) { timeout_set(&mesh->loop, &mesh->past_request_timeout, &(struct timeval) { - 10, rand() % 100000 - }); + 10, rand() % 100000 + }); + } } bool seen_request(meshlink_handle_t *mesh, const char *request) { @@ -216,16 +217,23 @@ bool seen_request(meshlink_handle_t *mesh, const char *request) { new = xmalloc(sizeof(*new)); new->request = xstrdup(request); new->firstseen = mesh->loop.now.tv_sec; + + if(!mesh->past_request_tree->head) { + timeout_set(&mesh->loop, &mesh->past_request_timeout, &(struct timeval) { + 10, rand() % 100000 + }); + } + splay_insert(mesh->past_request_tree, new); - timeout_add(&mesh->loop, &mesh->past_request_timeout, age_past_requests, NULL, &(struct timeval) { - 10, rand() % 100000 - }); return false; } } void init_requests(meshlink_handle_t *mesh) { mesh->past_request_tree = splay_alloc_tree((splay_compare_t) past_request_compare, (splay_action_t) free_past_request); + timeout_add(&mesh->loop, &mesh->past_request_timeout, age_past_requests, NULL, &(struct timeval) { + 0, 0 + }); } void exit_requests(meshlink_handle_t *mesh) { -- 2.39.5