From 0496523d3c1ac874eeecbb0ecb6516d88438d3c9 Mon Sep 17 00:00:00 2001 From: Mohammed Rafi KC Date: Mon, 1 Apr 2019 14:44:20 +0530 Subject: client/fini: return fini after rpc cleanup There is a race condition in rpc_transport later and client fini. Sequence of events to happen the race condition 1) When we want to destroy a graph, we send a parent down event first 2) Once parent down received on a client xlator, we will initiates a rpc disconnect 3) This will in turn generates a child down event. 4) When we process child down, we first do fini for Every xlator 5) On successful return of fini, we delete the graph Here after the step 5, there is a chance that the fini on client might not be finished. Because an rpc_tranpsort ref can race with the above sequence. So we have to wait till all rpc's are successfully freed before returning the fini from client Change-Id: I20145662d71fb837e448a4d3210d1fcb2855f2d4 fixes: bz#1659708 Signed-off-by: Mohammed Rafi KC --- xlators/protocol/client/src/client.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'xlators/protocol/client/src/client.c') diff --git a/xlators/protocol/client/src/client.c b/xlators/protocol/client/src/client.c index fffe22380b1..d7a0d1a1c9a 100644 --- a/xlators/protocol/client/src/client.c +++ b/xlators/protocol/client/src/client.c @@ -49,11 +49,12 @@ client_fini_complete(xlator_t *this) if (!conf->destroy) return 0; - this->private = NULL; - - pthread_spin_destroy(&conf->fd_lock); - pthread_mutex_destroy(&conf->lock); - GF_FREE(conf); + pthread_mutex_lock(&conf->lock); + { + conf->fini_completed = _gf_true; + pthread_cond_broadcast(&conf->fini_complete_cond); + } + pthread_mutex_unlock(&conf->lock); out: return 0; @@ -2723,6 +2724,7 @@ init(xlator_t *this) goto out; pthread_mutex_init(&conf->lock, NULL); + pthread_cond_init(&conf->fini_complete_cond, NULL); pthread_spin_init(&conf->fd_lock, 0); INIT_LIST_HEAD(&conf->saved_fds); @@ -2781,6 +2783,7 @@ fini(xlator_t *this) if (!conf) return; + conf->fini_completed = _gf_false; conf->destroy = 1; if (conf->rpc) { /* cleanup the saved-frames before last unref */ @@ -2788,6 +2791,18 @@ fini(xlator_t *this) rpc_clnt_unref(conf->rpc); } + pthread_mutex_lock(&conf->lock); + { + while (!conf->fini_completed) + pthread_cond_wait(&conf->fini_complete_cond, &conf->lock); + } + pthread_mutex_unlock(&conf->lock); + + pthread_spin_destroy(&conf->fd_lock); + pthread_mutex_destroy(&conf->lock); + pthread_cond_destroy(&conf->fini_complete_cond); + GF_FREE(conf); + /* Saved Fds */ /* TODO: */ -- cgit