From f1da2daf8325e437c66e2e0741ff6ce705382886 Mon Sep 17 00:00:00 2001 From: lilinzhe Date: Wed, 5 Apr 2017 21:43:10 +0800 Subject: [PATCH] fix: channel race condition of ephemeral channel destroy & recreate @see https://github.com/nsqio/go-nsq/issues/206 --- nsqd/topic.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/nsqd/topic.go b/nsqd/topic.go index 4c3ee2560..28cae7dfb 100644 --- a/nsqd/topic.go +++ b/nsqd/topic.go @@ -100,13 +100,23 @@ func (t *Topic) GetChannel(channelName string) *Channel { // this expects the caller to handle locking func (t *Topic) getOrCreateChannel(channelName string) (*Channel, bool) { + // block read when delete channel + t.RLock() channel, ok := t.channelMap[channelName] + t.RUnlock() if !ok { deleteCallback := func(c *Channel) { t.DeleteExistingChannel(c.name) } channel = NewChannel(t.name, channelName, t.ctx, deleteCallback) + t.Lock() + // avoid re-create channel + if oldchannel, ok := t.channelMap[channelName]; ok { + t.Unlock() + return oldchannel, false + } t.channelMap[channelName] = channel + t.Unlock() t.ctx.nsqd.logf("TOPIC(%s): new channel(%s)", t.name, channel.name) return channel, true }