Comments (6)
@hulkingshtick Our full test suite runs in -race
mode and has not reported problems, but of course coverage is far from 100%, so there's a chance there could be races. We'll keep monitoring.
from mux.
The test below- while it doesn't yet replicate this- when it's run with -race
, gives a similar stack trace from the race detector (the lines are off by a couple presumably due to version differences), and seems similar to #742:
func TestConcurrentRouteMatchingAndModification(t *testing.T) {
r := NewRouter()
var wg sync.WaitGroup
concurrency := 1000
panicChan := make(chan interface{}, concurrency)
for i := 0; i < concurrency; i++ {
wg.Add(1)
go func(i int) {
defer func() {
if re := recover(); re != nil {
panicChan <- re
}
}()
defer wg.Done()
if i%2 == 0 {
r.HandleFunc(
fmt.Sprintf("/test/%d/{id:[0-9]+}", i),
func(w http.ResponseWriter, r *http.Request) {
defer func() {
if perr := recover(); perr != nil {
t.Fatalf("%v", perr)
}
}()
// t.Logf("request: %s", r.RequestURI)
},
)
} else {
req := httptest.NewRequest(
"GET",
fmt.Sprintf("/test/%d/123", i-1),
nil,
)
w := httptest.NewRecorder()
r.ServeHTTP(w, req)
}
}(i)
}
wg.Wait()
close(panicChan)
for p := range panicChan {
t.Errorf("Panic occurred: %v", p)
}
}
Data races:
Read at 0x00c00023a550 by goroutine 9:
github.com/gorilla/mux.(*routeRegexp).Match()
/home/arcward/dev/mux/regexp.go:190 +0x54
github.com/gorilla/mux.(*Route).Match()
/home/arcward/dev/mux/route.go:56 +0x144
github.com/gorilla/mux.(*Router).Match()
/home/arcward/dev/mux/mux.go:154 +0xbe
github.com/gorilla/mux.(*Router).ServeHTTP()
/home/arcward/dev/mux/mux.go:204 +0x1d2
github.com/gorilla/mux.TestConcurrentRouteMatchingAndModification.func1()
/home/arcward/dev/mux/route_test.go:328 +0x416
github.com/gorilla/mux.TestConcurrentRouteMatchingAndModification.gowrap1()
/home/arcward/dev/mux/route_test.go:330 +0x41
Previous write at 0x00c00023a550 by goroutine 10:
github.com/gorilla/mux.newRouteRegexp()
/home/arcward/dev/mux/regexp.go:157 +0xd3e
github.com/gorilla/mux.(*Route).addRegexpMatcher()
/home/arcward/dev/mux/route.go:259 +0x26f
github.com/gorilla/mux.(*Route).Path()
/home/arcward/dev/mux/route.go:427 +0x392
github.com/gorilla/mux.(*Router).HandleFunc()
/home/arcward/dev/mux/mux.go:345 +0x460
github.com/gorilla/mux.TestConcurrentRouteMatchingAndModification.func1()
/home/arcward/dev/mux/route_test.go:309 +0x248
github.com/gorilla/mux.TestConcurrentRouteMatchingAndModification.gowrap1()
/home/arcward/dev/mux/route_test.go:330 +0x41
==================
WARNING: DATA RACE
Read at 0x00c00023e270 by goroutine 9:
regexp.(*Regexp).doExecute()
/home/arcward/sdk/go1.22.5/src/regexp/exec.go:527 +0xfd
regexp.(*Regexp).doMatch()
/home/arcward/sdk/go1.22.5/src/regexp/exec.go:514 +0x344
regexp.(*Regexp).MatchString()
/home/arcward/sdk/go1.22.5/src/regexp/regexp.go:531 +0x315
github.com/gorilla/mux.(*routeRegexp).Match()
/home/arcward/dev/mux/regexp.go:208 +0x2bb
github.com/gorilla/mux.(*Route).Match()
/home/arcward/dev/mux/route.go:56 +0x144
github.com/gorilla/mux.(*Router).Match()
/home/arcward/dev/mux/mux.go:154 +0xbe
github.com/gorilla/mux.(*Router).ServeHTTP()
/home/arcward/dev/mux/mux.go:204 +0x1d2
github.com/gorilla/mux.TestConcurrentRouteMatchingAndModification.func1()
/home/arcward/dev/mux/route_test.go:328 +0x416
github.com/gorilla/mux.TestConcurrentRouteMatchingAndModification.gowrap1()
/home/arcward/dev/mux/route_test.go:330 +0x41
Previous write at 0x00c00023e270 by goroutine 10:
regexp.compile()
/home/arcward/sdk/go1.22.5/src/regexp/regexp.go:188 +0x2ad
regexp.Compile()
/home/arcward/sdk/go1.22.5/src/regexp/regexp.go:135 +0x3a
github.com/gorilla/mux.newRouteRegexp()
/home/arcward/dev/mux/regexp.go:132 +0xbad
github.com/gorilla/mux.(*Route).addRegexpMatcher()
/home/arcward/dev/mux/route.go:259 +0x26f
github.com/gorilla/mux.(*Route).Path()
/home/arcward/dev/mux/route.go:427 +0x392
github.com/gorilla/mux.(*Router).HandleFunc()
/home/arcward/dev/mux/mux.go:345 +0x460
github.com/gorilla/mux.TestConcurrentRouteMatchingAndModification.func1()
/home/arcward/dev/mux/route_test.go:309 +0x248
github.com/gorilla/mux.TestConcurrentRouteMatchingAndModification.gowrap1()
/home/arcward/dev/mux/route_test.go:330 +0x41
I was able to eliminate the races by adding mutexes to:
Router.HandleFunc()
(Lock)Router.Path()
(RLock)Route.Match()
(RLock)Route.Handler()
(Lock)Route.Path()
(Lock - modifies regex matchers)
The race at least seems to be from functions being able to concurrently read/copy/modify routeConf.matchers
, and I'd be curious if eliminating the race would resolve the issue here... but like I said, I have to poke around a bit more to try to fully replicate it to induce a panic (there's stuff happening when adding a new path that I'm not totally familiar with at the moment)
from mux.
@arcward The mux does not support modifying routes concurrently with serving requests. Applications should assume this restriction following Go conventions (concurrency is not supported unless explicitly stated). Perhaps the documentation should be updated to explicitly state the restriction.
@streamer45 Does your application modify the routes concurrently with serving requests? Try running the application with the Data Race Detector to see if the detector reports any problems.
from mux.
The panic indicates that the field routeRegexp.regexp == nil.
I cannot find a code path that will set the field to nil, even in the presence of a data race. I am leaving this comment in case it helps another investigator.
from mux.
Very interesting thanks for sharing. If I am able to get around to this I’ll test it out
from mux.
@hulkingshtick Entendu, and for normal usage, absolutely. After the nil I saw 'sentry' and 'automation' and suspected it may be something that (maybe only) happens in test cases. I honed in on copyRouteConf
for the test which seems to line up, though it's difficult to reproduce (data races tend to make for unpredictable outcomes)
from mux.
Related Issues (20)
- CORS ERROR HOT 10
- JSON parsing failed HOT 7
- [BUG] Go can't find v2.0 HOT 1
- [BUG] MethodNotAllowedHandler does not work for subrouter with different routes HOT 9
- [BUG] Router does not distinguish between `/` and `%2F` in the request path HOT 1
- Cannot install gorilla/mux with new install command of go HOT 2
- [BUG] Index out of range in (*routeRegexp).Match HOT 1
- [FEATURE] Accidental omission of GetHeaders? HOT 1
- [BUG] API is probably broken for GetQueries per each method HOT 1
- [FEATURE] Route metadata
- When I use the subrouter() method, Methods() only works on the last endpoint, and other than the last endpoint, the rest of the endpoints give a 404 instead of a 405 with the unrelated http method. HOT 3
- router.Host not working for me
- [FEATURE] Support multi-value query string parameters HOT 3
- [BUG] handler and middleware running twice with middleware defined on pointer reciever
- the Wrapped Gorilla Websocket connection by Gorilla Mux, does not work within the docker container. HOT 1
- [FEATURE] Ignore case sensitivity when matching defined methods HOT 3
- [BUG] <Docker build problems with go get command> HOT 4
- WithContext breaks mux.Vars HOT 2
- [BUG] Error causing build image to fail when creating buildagent via Dockerfile. Error: undefined : any HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from mux.