From 46c15ea8fa98bb3d92580b192f03863c2e2a2d9c Mon Sep 17 00:00:00 2001 From: Mohit Agrawal Date: Thu, 29 Nov 2018 19:55:39 +0530 Subject: server: Resolve memory leak path in server_init Problem: 1) server_init does not cleanup allocate resources while it is failed before return error 2) dict leak at the time of graph destroying Solution: 1) free resources in case of server_init is failed 2) Take dict_ref of graph xlator before destroying the graph to avoid leak Change-Id: I9e31e156b9ed6bebe622745a8be0e470774e3d15 fixes: bz#1654917 Signed-off-by: Mohit Agrawal --- xlators/mgmt/glusterd/src/glusterd-utils.c | 33 ++---------------- xlators/protocol/server/src/server.c | 54 +++++++++++++++++++++++++----- 2 files changed, 47 insertions(+), 40 deletions(-) (limited to 'xlators') diff --git a/xlators/mgmt/glusterd/src/glusterd-utils.c b/xlators/mgmt/glusterd/src/glusterd-utils.c index 2deda2945c0..cdac6d5b8bf 100644 --- a/xlators/mgmt/glusterd/src/glusterd-utils.c +++ b/xlators/mgmt/glusterd/src/glusterd-utils.c @@ -9301,35 +9301,6 @@ glusterd_defrag_volume_status_update(glusterd_volinfo_t *volinfo, return ret; } -/* - The function is required to take dict ref for every xlator at graph. - At the time of compare graph topology create a graph and populate - key values in the dictionary, after finished graph comparison we do destroy - the new graph.At the time of construct graph we don't take any reference - so to avoid leak due to ref counter underflow we need to call dict_ref here. - -*/ - -void -glusterd_graph_take_reference(xlator_t *tree) -{ - xlator_t *trav = tree; - xlator_t *prev = tree; - - if (!tree) { - gf_msg("parser", GF_LOG_ERROR, 0, LG_MSG_TREE_NOT_FOUND, - "Translator tree not found"); - return; - } - - while (prev) { - trav = prev->next; - if (prev->options) - dict_ref(prev->options); - prev = trav; - } - return; -} int glusterd_check_topology_identical(const char *filename1, const char *filename2, @@ -9376,14 +9347,14 @@ glusterd_check_topology_identical(const char *filename1, const char *filename2, if (grph1 == NULL) goto out; - glusterd_graph_take_reference(grph1->first); + gluster_graph_take_reference(grph1->first); /* create the graph for filename2 */ grph2 = glusterfs_graph_construct(fp2); if (grph2 == NULL) goto out; - glusterd_graph_take_reference(grph2->first); + gluster_graph_take_reference(grph2->first); /* compare the graph topology */ *identical = is_graph_topology_equal(grph1, grph2); diff --git a/xlators/protocol/server/src/server.c b/xlators/protocol/server/src/server.c index 77e5d74e7c5..81aa72fbbc0 100644 --- a/xlators/protocol/server/src/server.c +++ b/xlators/protocol/server/src/server.c @@ -986,6 +986,49 @@ server_dump_metrics(xlator_t *this, int fd) return 0; } +void +server_cleanup(xlator_t *this, server_conf_t *conf) +{ + if (!this || !conf) + return; + + LOCK_DESTROY(&conf->itable_lock); + pthread_mutex_destroy(&conf->mutex); + + if (this->ctx->event_pool) { + /* Free the event pool */ + (void)event_pool_destroy(this->ctx->event_pool); + } + + if (dict_get(this->options, "config-directory")) { + GF_FREE(conf->conf_dir); + conf->conf_dir = NULL; + } + + if (conf->child_status) { + GF_FREE(conf->child_status); + conf->child_status = NULL; + } + + if (this->ctx->statedump_path) { + GF_FREE(this->ctx->statedump_path); + this->ctx->statedump_path = NULL; + } + + if (conf->auth_modules) { + gf_auth_fini(conf->auth_modules); + dict_unref(conf->auth_modules); + } + + if (conf->rpc) { + (void)rpcsvc_destroy(conf->rpc); + conf->rpc = NULL; + } + + GF_FREE(conf); + this->private = NULL; +} + int server_init(xlator_t *this) { @@ -1061,6 +1104,7 @@ server_init(xlator_t *this) ret = gf_auth_init(this, conf->auth_modules); if (ret) { dict_unref(conf->auth_modules); + conf->auth_modules = NULL; goto out; } @@ -1239,15 +1283,7 @@ out: if (this != NULL) { this->fini(this); } - - if (conf && conf->rpc) { - rpcsvc_listener_t *listener, *next; - list_for_each_entry_safe(listener, next, &conf->rpc->listeners, - list) - { - rpcsvc_listener_destroy(listener); - } - } + server_cleanup(this, conf); } return ret; -- cgit