From 693eccd456c4fc7dfadb72069da906544cf19733 Mon Sep 17 00:00:00 2001 From: Zhou Zhengping Date: Sun, 26 Jun 2016 19:56:58 -0400 Subject: libglusterfs: race condition when set ctx->timer in function gf_timer_registry_init 1.fix race conditon when set ctx->timer 2.use typical list_head operation instead of verbose list's operation 3.add file "tags" into .gitignore Signed-off-by: Zhou Zhengping Change-Id: I4ec55e41356633cf1399536d202c58e19b309f00 BUG: 1350191 Reviewed-on: http://review.gluster.org/14800 Smoke: Gluster Build System Tested-by: Zhou Zhengping CentOS-regression: Gluster Build System NetBSD-regression: NetBSD Build System Reviewed-by: Jeff Darcy --- libglusterfs/src/timer.c | 77 +++++++++++++++++++----------------------------- 1 file changed, 30 insertions(+), 47 deletions(-) (limited to 'libglusterfs/src/timer.c') diff --git a/libglusterfs/src/timer.c b/libglusterfs/src/timer.c index bcdc5da5571..a24a07804a8 100644 --- a/libglusterfs/src/timer.c +++ b/libglusterfs/src/timer.c @@ -57,16 +57,11 @@ gf_timer_call_after (glusterfs_ctx_t *ctx, event->xl = THIS; LOCK (®->lock); { - trav = reg->active.prev; - while (trav != ®->active) { + list_for_each_entry_reverse (trav, ®->active, list) { if (TS (trav->at) < at) break; - trav = trav->prev; } - event->prev = trav; - event->next = event->prev->next; - event->prev->next = event; - event->next->prev = event; + list_add (&event->list, &trav->list); } UNLOCK (®->lock); return event; @@ -105,9 +100,7 @@ gf_timer_call_cancel (glusterfs_ctx_t *ctx, fired = event->fired; if (fired) goto unlock; - - event->next->prev = event->prev; - event->prev->next = event->next; + list_del (&event->list); } unlock: UNLOCK (®->lock); @@ -120,20 +113,13 @@ unlock: } -static void -__delete_entry (gf_timer_t *event) { - event->next->prev = event->prev; - event->prev->next = event->next; - GF_FREE (event); -} - - static void * gf_timer_proc (void *data) { gf_timer_registry_t *reg = data; const struct timespec sleepts = {.tv_sec = 1, .tv_nsec = 0, }; gf_timer_t *event = NULL; + gf_timer_t *tmp = NULL; xlator_t *old_THIS = NULL; while (!reg->fin) { @@ -148,13 +134,15 @@ gf_timer_proc (void *data) LOCK (®->lock); { - event = reg->active.next; - at = TS (event->at); - if (event != ®->active && now >= at) { - need_cbk = 1; - event->next->prev = event->prev; - event->prev->next = event->next; - event->fired = _gf_true; + list_for_each_entry_safe (event, + tmp, ®->active, list) { + at = TS (event->at); + if (now >= at) { + need_cbk = 1; + event->fired = _gf_true; + list_del (&event->list); + break; + } } } UNLOCK (®->lock); @@ -181,11 +169,9 @@ gf_timer_proc (void *data) /* Do not call gf_timer_call_cancel(), * it will lead to deadlock */ - while (reg->active.next != ®->active) { - event = reg->active.next; - /* cannot call list_del as the event doesnt have - * list_head*/ - __delete_entry (event); + list_for_each_entry_safe (event, tmp, ®->active, list) { + list_del (&event->list); + GF_FREE (event); } } UNLOCK (®->lock); @@ -216,26 +202,23 @@ gf_timer_registry_init (glusterfs_ctx_t *ctx) LOCK (&ctx->lock); { reg = ctx->timer; - } - UNLOCK (&ctx->lock); - if (!reg) { + if (reg) { + UNLOCK (&ctx->lock); + goto out; + } reg = GF_CALLOC (1, sizeof (*reg), - gf_common_mt_gf_timer_registry_t); - if (!reg) - return NULL; - - LOCK_INIT (®->lock); - reg->active.next = ®->active; - reg->active.prev = ®->active; - - LOCK (&ctx->lock); - { - ctx->timer = reg; + gf_common_mt_gf_timer_registry_t); + if (!reg) { + UNLOCK (&ctx->lock); + goto out; } - UNLOCK (&ctx->lock); - gf_thread_create (®->th, NULL, gf_timer_proc, reg); + ctx->timer = reg; + LOCK_INIT (®->lock); + INIT_LIST_HEAD (®->active); } - + UNLOCK (&ctx->lock); + gf_thread_create (®->th, NULL, gf_timer_proc, reg); +out: return reg; } -- cgit