From 8dc00f5fc6bbc9e560b8298f8bb806246a0a3b0e Mon Sep 17 00:00:00 2001 From: NADAL Jean-Baptiste Date: Mon, 17 Feb 2020 13:27:42 +0100 Subject: [PATCH] Fix Memory leaks. --- src/rest/restd.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++-- src/rest/restd.h | 2 ++ 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/src/rest/restd.c b/src/rest/restd.c index 113d538..e10231c 100644 --- a/src/rest/restd.c +++ b/src/rest/restd.c @@ -45,6 +45,12 @@ static bool initialized = false; */ int _restd_log_level = RESTD_LOG_WARN; + +char *restd_server_get_option(restd_server_t *server, const char *key); +int restd_server_get_option_int(restd_server_t *server, const char *key); +static void close_server(restd_server_t *server); +static int notify_loopexit(restd_server_t *server); + /*--------------------------- PUBLIC FUNCTIONS -------------------------------*/ /** @@ -108,7 +114,7 @@ void restd_server_free(restd_server_t *server) { if (server == NULL) return; -#if 0 + int thread = restd_server_get_option_int(server, "server.thread"); if (thread && server->thread) { @@ -144,7 +150,7 @@ void restd_server_free(restd_server_t *server) } server->hooks->free(server->hooks); } -#endif + free(server); DEBUG("Server terminated."); } @@ -181,3 +187,61 @@ void restd_server_register_hook_on_path(restd_server_t *server, const char *meth } /*--------------------------- LOCAL FUNCTIONS -------------------------------*/ + +/** + * Retrieve server option. + */ +char *restd_server_get_option(restd_server_t *server, const char *key) +{ + return server->options->getstr(server->options, key, false); +} + +/** + * Retrieve server option in integer format. + */ +int restd_server_get_option_int(restd_server_t *server, const char *key) +{ + char *value = restd_server_get_option(server, key); + return (value) ? atoi(value) : 0; +} + +/*--------------------------------------------------------------------------*/ + +static void close_server(restd_server_t *server) +{ + DEBUG("Closing server."); + + if (server->notify_buffer) + { + bufferevent_free(server->notify_buffer); + server->notify_buffer = NULL; + } + + if (server->listener) + { + evconnlistener_free(server->listener); + server->listener = NULL; + } + + if (server->thread) + { + void *retval = NULL; + DEBUG("Waiting server's last loop to finish."); + pthread_join(*(server->thread), &retval); + free(retval); + free(server->thread); + server->thread = NULL; + } + INFO("Server closed."); +} + +/** + * If there's no event, loopbreak or loopexit call won't work until one more + * event arrived. So we use eventfd as a internal notification channel to let + * server get out of the loop without waiting for an event. + */ +static int notify_loopexit(restd_server_t *server) +{ + uint64_t x = 0; + return bufferevent_write(server->notify_buffer, &x, sizeof(uint64_t)); +} diff --git a/src/rest/restd.h b/src/rest/restd.h index 1760128..4ca23b9 100644 --- a/src/rest/restd.h +++ b/src/rest/restd.h @@ -37,6 +37,8 @@ typedef struct restd_server_s restd_server_t; typedef struct restd_hook_s restd_hook_t; +typedef int (*restd_callback)(short event, void *conn, void *userdata); + /*------------------------------- INCLUDES ----------------------------------*/ extern restd_server_t *restd_server_new(void);