syncutil: in RWMutexTracker, log.Fatal instead of panic on double-RLock

Change-Id: Ifc34b29fb8264f96e2e9516948d9c0b4bfff984a
This commit is contained in:
Brad Fitzpatrick 2013-12-24 13:40:48 -08:00
parent f8d9e6663d
commit d7c58ebc7c
1 changed files with 17 additions and 3 deletions

View File

@ -115,12 +115,12 @@ func (m *RWMutexTracker) Lock() {
atomic.AddInt32(&m.nhavew, 1) atomic.AddInt32(&m.nhavew, 1)
m.hmu.Lock() m.hmu.Lock()
defer m.hmu.Unlock()
if len(m.holder) == 0 { if len(m.holder) == 0 {
m.holder = make([]byte, stackBufSize) m.holder = make([]byte, stackBufSize)
} }
m.holder = m.holder[:runtime.Stack(m.holder[:stackBufSize], false)] m.holder = m.holder[:runtime.Stack(m.holder[:stackBufSize], false)]
log.Printf("Lock at %s", string(m.holder)) log.Printf("Lock at %s", string(m.holder))
m.hmu.Unlock()
} }
func (m *RWMutexTracker) Unlock() { func (m *RWMutexTracker) Unlock() {
@ -135,20 +135,34 @@ func (m *RWMutexTracker) Unlock() {
func (m *RWMutexTracker) RLock() { func (m *RWMutexTracker) RLock() {
m.logOnce.Do(m.startLogger) m.logOnce.Do(m.startLogger)
atomic.AddInt32(&m.nwaitr, 1) atomic.AddInt32(&m.nwaitr, 1)
// Catch read-write-read lock. See if somebody (us? via
// another goroutine?) already has a read lock, and then
// somebody else is waiting to write, meaning our second read
// will deadlock.
if atomic.LoadInt32(&m.nhaver) > 0 && atomic.LoadInt32(&m.nwaitw) > 0 {
buf := getBuf()
buf = buf[:runtime.Stack(buf, false)]
log.Printf("Potential R-W-R deadlock at: %s", buf)
putBuf(buf)
}
m.mu.RLock() m.mu.RLock()
atomic.AddInt32(&m.nwaitr, -1) atomic.AddInt32(&m.nwaitr, -1)
atomic.AddInt32(&m.nhaver, 1) atomic.AddInt32(&m.nhaver, 1)
gid := GoroutineID() gid := GoroutineID()
m.hmu.Lock() m.hmu.Lock()
defer m.hmu.Unlock()
if m.holdr == nil { if m.holdr == nil {
m.holdr = make(map[int64]bool) m.holdr = make(map[int64]bool)
} }
if m.holdr[gid] { if m.holdr[gid] {
panic("Recursive call to RLock") buf := getBuf()
buf = buf[:runtime.Stack(buf, false)]
log.Fatalf("Recursive call to RLock: %s", buf)
} }
m.holdr[gid] = true m.holdr[gid] = true
m.hmu.Unlock()
} }
func stack() []byte { func stack() []byte {