From e207a3ce65323c3dda7cd8133fe14f4f1efd2500 Mon Sep 17 00:00:00 2001 From: Raphael Gavache Date: Tue, 26 Feb 2019 08:10:16 +0100 Subject: [PATCH] Fix context.Copy() race condition (#1020) * Fix context.Copy race condition * Update githubapi_test.go * fix code format --- context.go | 4 ++++ context_test.go | 2 ++ githubapi_test.go | 23 +++++++++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/context.go b/context.go index fa63ec8ba2..7618cef5bd 100644 --- a/context.go +++ b/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 } diff --git a/context_test.go b/context_test.go index 34cc71a501..dc8ac30628 100644 --- a/context_test.go +++ b/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) { diff --git a/githubapi_test.go b/githubapi_test.go index 29aa158478..fb74d65940 100644 --- a/githubapi_test.go +++ b/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) {