New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
sync: panic unlock mutex from sync.Once #16762
Comments
Can you point us at the code, at the revision matching the stack trace above? I suspect it's just a locking bug or data race in Docker because I've never seen this bug reported, and this code is exercised heavily by everybody. Is this easily reproducible? Have you seen multiple reports of this? |
Line is from here: https://github.com/docker/docker/blob/v1.11.2/vendor/src/github.com/docker/libnetwork/resolver.go#L355 AFAICT the panic is happening from the defer Unlock in sync.Once. |
The code looks a little suspicious. There's code in func (r *resolver) FlushExtServers() {
for i := 0; i < maxExtDNS; i++ {
if r.extDNSList[i].extConn != nil {
r.extDNSList[i].extConn.Close()
}
r.extDNSList[i].extConn = nil
r.extDNSList[i].extOnce = sync.Once{}
}
} And that is part of the // FlushExtServers clears the cached UDP connections to external
// nameservers
FlushExtServers() And is call by func (ep *endpoint) Join(sbox Sandbox, options ...EndpointOption) error { I'm going to close this bug for now. I think you need to do an audit of libnetwork's locking. |
I've made the mistake myself, it's not a data race and more about getting types wrong than locks wrong. A convoluted repro: https://play.golang.org/p/xPULnrVKiY Do() takes the address of the Once, locks m, invokes f(), f changes what *Once is pointing at, Unlock panics because m isn't the m that was locked. It would be nice if the race detector also looked for "static hazard" problems like this. As go vet carps when you copy a mutex (containing) that's not a pointer it might be worthwhile to have it complain when a mutex (containing) that's not a pointer is assigned to by operator, as there's probably never a case where that expresses what's intended. |
Please answer these questions before submitting your issue. Thanks!
go version
)?1.5.4
go env
)?linux/amd64
Normal usage of Docker.
Docker is (was) using a
sync.Once
in a function that handles DNS requests. Naturally this function can get called often and with a lot of concurrency depending on the user.sync.Once should never panic
During operation a user reported this panic:
Note this panic (unlock of unlocked mutex) is happening as a result of a call to
once.Do(func() {...})
in the slow path where theonce
does adefer o.m.Unlock()
The text was updated successfully, but these errors were encountered: