From 73ccfea3ba5a115e74177dbfbc1ea0fff88c13f4 Mon Sep 17 00:00:00 2001 From: AcoNCodes Date: Mon, 16 Mar 2020 18:52:02 +0200 Subject: [PATCH] Add mutex for protect Context.Keys map (#1391) * Add mutex for protect Context.Keys map * Fix tests Co-authored-by: Nikolay Tolkachov Co-authored-by: Bo-Yi Wu --- context.go | 10 ++++++++++ gin.go | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/context.go b/context.go index 1d3e665282..572dbb81bb 100644 --- a/context.go +++ b/context.go @@ -16,6 +16,7 @@ import ( "net/url" "os" "strings" + "sync" "time" "github.com/gin-contrib/sse" @@ -52,6 +53,9 @@ type Context struct { engine *Engine + // This mutex protect Keys map + KeysMutex *sync.RWMutex + // Keys is a key/value pair exclusively for the context of each request. Keys map[string]interface{} @@ -78,6 +82,7 @@ func (c *Context) reset() { c.Params = c.Params[0:0] c.handlers = nil c.index = -1 + c.KeysMutex = &sync.RWMutex{} c.fullPath = "" c.Keys = nil c.Errors = c.Errors[0:0] @@ -219,16 +224,21 @@ func (c *Context) Error(err error) *Error { // Set is used to store a new key/value pair exclusively for this context. // It also lazy initializes c.Keys if it was not used previously. func (c *Context) Set(key string, value interface{}) { + c.KeysMutex.Lock() if c.Keys == nil { c.Keys = make(map[string]interface{}) } + c.Keys[key] = value + c.KeysMutex.Unlock() } // Get returns the value for the given key, ie: (value, true). // If the value does not exists it returns (nil, false) func (c *Context) Get(key string) (value interface{}, exists bool) { + c.KeysMutex.RLock() value, exists = c.Keys[key] + c.KeysMutex.RUnlock() return } diff --git a/gin.go b/gin.go index ab1d0a4684..1c2acbc8f4 100644 --- a/gin.go +++ b/gin.go @@ -162,7 +162,7 @@ func Default() *Engine { } func (engine *Engine) allocateContext() *Context { - return &Context{engine: engine} + return &Context{engine: engine, KeysMutex: &sync.RWMutex{}} } // Delims sets template left and right delims and returns a Engine instance.