I got a race condition when getting value from Context
: concurrent map read and map write
The potential error code is in /gin-gonic/gin/context.go
// Set is used to store a new key/value pair exclusivelly for this context.
// It also lazy initializes c.Keys if it was not used previously.
func (c *Context) Set(key string, value interface{}) {
if c.Keys == nil {
c.Keys = make(map[string]interface{})
}
c.Keys[key] = value
}
// 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) {
if c.Keys != nil {
value, exists = c.Keys[key]
}
return
}
I thought here we must use Mutex around c.Keys[key]
to avoid the race condition.
Comment From: crazbot
is the Context often used as a container or something else?
Comment From: ntquyen
Yes, it is used as a map to store header values and some request metrics
Comment From: crazbot
okay, uh, so the Context is commonly used as a single entity. well, we should use Mutex in our logic instead of directly bind a Mutex to the Contexts.
Comment From: stxml
Should we orient ourselves toward context.Context? It is safe to use concurrently and gin.Context implements the interface.
Comment From: NeoCN
any update on this issue?
Comment From: maxatome
As I just commented in pull request #702, putting a Mutex around c.Keys is a bad idea due to the recycling logic gin gonic applies to Context instances. You have to do a copy of the context (or of the Keys map) before sharing it, then handle the locking mechanism at your level.
Comment From: NeoCN
Because of the recycling logic gin applies to Context, we can not simply use gin.Context and must do c.Copy for continue use(may be used in a goroutine), and this result that we do c.Copy nearly almost every method. Just thinking about we need an option to disable recycling logic for gin.Context.
Comment From: themartorana
Not sure if anyone started getting this issue with Go 1.8, but we did - a lot. (We just deployed to production with 1.8 for the first time today.)
Looks like 1.8 added a new check. From https://stackoverflow.com/questions/42453442/concurrent-map-iteration-and-map-write-error-in-golang-1-8 :
There is a enhanced concurrent access check added in the Golang 1.8, and this is the source code in runtime/hashmap.go:736,
if h.flags&hashWriting != 0 { throw("concurrent map iteration and map write") }
I'm trying to work around it right now, but I may be forced to toss a mutex lock into our vendor copy of Gin in the meantime (or roll back to 1.7)...
Comment From: rkuska
FYI This issue should be closed gin.Context
has a RWMutex
for safeguarding since v1.6.0
.
Comment From: niboge
FYI This issue should be closed
gin.Context
has aRWMutex
for safeguarding sincev1.6.0
.
set header 、 set response , is it safe too?
Comment From: guoruibiao
I find this question @v1.4.0, question could go to sleep finally. Thx this issue.
Comment From: BhatnagarPratham
FYI This issue should be closed
gin.Context
has aRWMutex
for safeguarding sincev1.6.0
.set header 、 set response , is it safe too?
set header is also not concurrent write safe, can lead to:
"fatal error: concurrent map writes"