-
Notifications
You must be signed in to change notification settings - Fork 8.5k
Open
Labels
type/bugFound something you weren't expecting? Report it here!Found something you weren't expecting? Report it here!
Description
Description
Running the following test with -race trips the race detector:
func TestRepro(t *testing.T) {
r := gin.New()
go r.Routes() // could also be server startup + send request
r.GET("/", func(ctx *gin.Context) {
ctx.String(200, "OK")
})
time.Sleep(time.Second)
}
Output:
==================
WARNING: DATA RACE
Read at 0x00c0001b94c8 by goroutine 8:
github.com/gin-gonic/gin.(*Engine).Routes()
/Users/maxsours/go/pkg/mod/github.com/gin-gonic/[email protected]/gin.go:381 +0x3c
max-assess-app.TestRepro.gowrap1()
/Users/maxsours/Documents/go/max-assess-app/main_test.go:20 +0x20
Previous write at 0x00c0001b94c8 by goroutine 7:
github.com/gin-gonic/gin.(*Engine).addRoute()
/Users/maxsours/go/pkg/mod/github.com/gin-gonic/[email protected]/gin.go:365 +0x22c
github.com/gin-gonic/gin.(*RouterGroup).handle()
/Users/maxsours/go/pkg/mod/github.com/gin-gonic/[email protected]/routergroup.go:89 +0x14c
github.com/gin-gonic/gin.(*RouterGroup).GET()
/Users/maxsours/go/pkg/mod/github.com/gin-gonic/[email protected]/routergroup.go:117 +0x104
max-assess-app.TestRepro()
/Users/maxsours/Documents/go/max-assess-app/main_test.go:21 +0x94
testing.tRunner()
/usr/local/go/src/testing/testing.go:1934 +0x164
testing.(*T).Run.gowrap1()
/usr/local/go/src/testing/testing.go:1997 +0x3c
I believe this is due to a lack of concurrent safety when accessing gin.Engine.trees. One goroutine iterates through trees while another goroutine calls appends to it. The analogous operation on http.ServeMux is concurrent-safe due to their use of a sync.RWMutex when adding/reading new route patterns:
https://cs.opensource.google/go/go/+/refs/tags/go1.25.4:src/net/http/server.go;l=2940
Gin Version
v1.11.0
Can you reproduce the bug?
Yes
Source Code
Run the following test with -race:
func TestRepro(t *testing.T) {
r := gin.New()
go r.Routes()
r.GET("/", func(ctx *gin.Context) {
ctx.String(200, "OK")
})
time.Sleep(time.Second)
}
Go Version
go1.25.4
Operating System
GOOS=darwin GOARCH=arm64
Metadata
Metadata
Assignees
Labels
type/bugFound something you weren't expecting? Report it here!Found something you weren't expecting? Report it here!