mirror of https://github.com/perkeep/perkeep.git
syncutil: in RWMutexTracker, log.Fatal instead of panic on double-RLock
Change-Id: Ifc34b29fb8264f96e2e9516948d9c0b4bfff984a
This commit is contained in:
parent
f8d9e6663d
commit
d7c58ebc7c
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue