From 811e0868ed9fedd6ed5edeee0df491d60af1edeb Mon Sep 17 00:00:00 2001 From: Ivan Kozlovic Date: Wed, 17 Aug 2016 16:46:34 -0600 Subject: [PATCH] [FIXED] Data RACE on Unsubscribe when client connection is closed Resolves #331 --- server/client.go | 4 +++- server/route.go | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/server/client.go b/server/client.go index 9b98a5d3..d231dad4 100644 --- a/server/client.go +++ b/server/client.go @@ -882,10 +882,12 @@ func (c *client) deliverMsg(sub *subscription, mh, msg []byte) { // unsubscribe and drop message on the floor. if sub.nm == sub.max { c.Debugf("Auto-unsubscribe limit of %d reached for sid '%s'\n", sub.max, string(sub.sid)) - defer client.unsubscribe(sub) + // Due to defer, reverse the code order so that execution + // is consistent with other cases where we unsubscribe. if shouldForward { defer client.srv.broadcastUnSubscribe(sub) } + defer client.unsubscribe(sub) } else if sub.nm > sub.max { c.Debugf("Auto-unsubscribe limit [%d] exceeded\n", sub.max) client.mu.Unlock() diff --git a/server/route.go b/server/route.go index 8eaa37b5..ffb3ca8b 100644 --- a/server/route.go +++ b/server/route.go @@ -575,10 +575,12 @@ func (s *Server) broadcastUnSubscribe(sub *subscription) { } rsid := routeSid(sub) maxStr := _EMPTY_ + sub.client.mu.Lock() // Set max if we have it set and have not tripped auto-unsubscribe if sub.max > 0 && sub.nm < sub.max { maxStr = fmt.Sprintf(" %d", sub.max) } + sub.client.mu.Unlock() proto := fmt.Sprintf(unsubProto, rsid, maxStr) s.broadcastInterestToRoutes(proto) }