Переглянути джерело

Fix context.Copy() race condition (#1020)

* Fix context.Copy race condition

* Update githubapi_test.go

* fix code format
Raphael Gavache 6 роки тому
батько
коміт
e207a3ce65
3 змінених файлів з 29 додано та 0 видалено
  1. 4 0
      context.go
  2. 2 0
      context_test.go
  3. 23 0
      githubapi_test.go

+ 4 - 0
context.go

@@ -82,6 +82,10 @@ func (c *Context) Copy() *Context {
 	cp.Writer = &cp.writermem
 	cp.index = abortIndex
 	cp.handlers = nil
+	cp.Keys = map[string]interface{}{}
+	for k, v := range c.Keys {
+		cp.Keys[k] = v
+	}
 	return &cp
 }
 

+ 2 - 0
context_test.go

@@ -331,6 +331,8 @@ func TestContextCopy(t *testing.T) {
 	assert.Equal(t, cp.Keys, c.Keys)
 	assert.Equal(t, cp.engine, c.engine)
 	assert.Equal(t, cp.Params, c.Params)
+	cp.Set("foo", "notBar")
+	assert.False(t, cp.Keys["foo"] == c.Keys["foo"])
 }
 
 func TestContextHandlerName(t *testing.T) {

+ 23 - 0
githubapi_test.go

@@ -346,6 +346,29 @@ func TestBindUriError(t *testing.T) {
 	assert.Equal(t, http.StatusBadRequest, w1.Code)
 }
 
+func TestRaceContextCopy(t *testing.T) {
+	DefaultWriter = os.Stdout
+	router := Default()
+	router.GET("/test/copy/race", func(c *Context) {
+		c.Set("1", 0)
+		c.Set("2", 0)
+
+		// Sending a copy of the Context to two separate routines
+		go readWriteKeys(c.Copy())
+		go readWriteKeys(c.Copy())
+		c.String(http.StatusOK, "run OK, no panics")
+	})
+	w := performRequest(router, "GET", "/test/copy/race")
+	assert.Equal(t, "run OK, no panics", w.Body.String())
+}
+
+func readWriteKeys(c *Context) {
+	for {
+		c.Set("1", rand.Int())
+		c.Set("2", c.Value("1"))
+	}
+}
+
 func githubConfigRouter(router *Engine) {
 	for _, route := range githubAPI {
 		router.Handle(route.method, route.path, func(c *Context) {