Fix context.Params race condition on Copy() (#1841)
* Fix context.Params race condition on Copy() Using context.Param(key) on a context.Copy inside a goroutine may lead to incorrect value on a high load, where another request overwrite a Param * Using waitgroup to wait asynchronous test case
This commit is contained in:
		@ -89,6 +89,9 @@ func (c *Context) Copy() *Context {
 | 
			
		||||
	for k, v := range c.Keys {
 | 
			
		||||
		cp.Keys[k] = v
 | 
			
		||||
	}
 | 
			
		||||
	paramCopy := make([]Param, len(cp.Params))
 | 
			
		||||
	copy(paramCopy, cp.Params)
 | 
			
		||||
	cp.Params = paramCopy
 | 
			
		||||
	return &cp
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -13,8 +13,10 @@ import (
 | 
			
		||||
	"mime/multipart"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/http/httptest"
 | 
			
		||||
	"os"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
@ -1821,3 +1823,24 @@ func TestContextResetInHandler(t *testing.T) {
 | 
			
		||||
		c.Next()
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestRaceParamsContextCopy(t *testing.T) {
 | 
			
		||||
	DefaultWriter = os.Stdout
 | 
			
		||||
	router := Default()
 | 
			
		||||
	nameGroup := router.Group("/:name")
 | 
			
		||||
	var wg sync.WaitGroup
 | 
			
		||||
	wg.Add(2)
 | 
			
		||||
	{
 | 
			
		||||
		nameGroup.GET("/api", func(c *Context) {
 | 
			
		||||
			go func(c *Context, param string) {
 | 
			
		||||
				defer wg.Done()
 | 
			
		||||
				// First assert must be executed after the second request
 | 
			
		||||
				time.Sleep(50 * time.Millisecond)
 | 
			
		||||
				assert.Equal(t, c.Param("name"), param)
 | 
			
		||||
			}(c.Copy(), c.Param("name"))
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	performRequest(router, "GET", "/name1/api")
 | 
			
		||||
	performRequest(router, "GET", "/name2/api")
 | 
			
		||||
	wg.Wait()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user