Skip to content

Commit 6ee36e1

Browse files
committed
improve deadlock error message
1 parent fecc21c commit 6ee36e1

File tree

1 file changed

+45
-30
lines changed

1 file changed

+45
-30
lines changed

deadlock.go

Lines changed: 45 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,18 @@ import (
1111
)
1212

1313
type Mutex struct {
14-
mointor
14+
monitor
1515
sync.Mutex
1616
}
1717

1818
func (m *Mutex) Lock() {
19-
holder, holderStack := m.mointor.wait()
19+
waitInfo := m.monitor.wait()
2020
m.Mutex.Lock()
21-
m.mointor.using(holder, holderStack)
21+
m.monitor.using(waitInfo)
2222
}
2323

2424
func (m *Mutex) Unlock() {
25-
m.mointor.release()
25+
m.monitor.release()
2626
m.Mutex.Unlock()
2727
}
2828

@@ -47,61 +47,76 @@ func (rw *RWMutex) RUnlock() {
4747
}
4848

4949
var (
50-
globalMutex = new(sync.Mutex)
51-
waitTargets = make(map[int32]*mointor)
52-
goroutineBegin = []byte("goroutine ")
53-
newline = []byte{'\n'}
50+
globalMutex = new(sync.Mutex)
51+
waitingList = make(map[int32]*waiting)
52+
titleStr = []byte("[DEAD LOCK]\n")
53+
goStr = []byte("goroutine ")
54+
waitStr = []byte(" wait")
55+
holdStr = []byte(" hold")
56+
lineStr = []byte{'\n'}
5457
)
5558

56-
type mointor struct {
59+
type monitor struct {
5760
holder int32
5861
holderStack debug.StackInfo
5962
}
6063

61-
func (m *mointor) wait() (int32, debug.StackInfo) {
64+
type waiting struct {
65+
monitor *monitor
66+
holder int32
67+
holderStack debug.StackInfo
68+
}
69+
70+
func (m *monitor) wait() *waiting {
6271
globalMutex.Lock()
6372
defer globalMutex.Unlock()
6473

65-
holder := goid.Get()
66-
holderStack := debug.StackTrace(3, 0)
67-
waitTargets[holder] = m
74+
waitInfo := &waiting{m, goid.Get(), debug.StackTrace(3, 0)}
75+
waitingList[waitInfo.holder] = waitInfo
6876

69-
m.verify([]*mointor{{holder, holderStack}})
77+
m.verify([]*waiting{waitInfo})
7078

71-
return holder, holderStack
79+
return waitInfo
7280
}
7381

74-
func (m *mointor) verify(holderLink []*mointor) {
82+
func (m *monitor) verify(waitLink []*waiting) {
7583
if m.holder != 0 {
7684
// deadlock detected
77-
if m.holder == holderLink[0].holder {
85+
if m.holder == waitLink[0].holder {
7886
buf := new(bytes.Buffer)
79-
buf.WriteString("[DEAD LOCK]\n")
80-
for i := 0; i < len(holderLink); i++ {
81-
buf.Write(goroutineBegin)
82-
buf.WriteString(strconv.Itoa(int(holderLink[i].holder)))
83-
buf.Write(newline)
84-
buf.Write(holderLink[i].holderStack.Bytes(" "))
87+
buf.Write(titleStr)
88+
for i := 0; i < len(waitLink); i++ {
89+
buf.Write(goStr)
90+
buf.WriteString(strconv.Itoa(int(waitLink[i].holder)))
91+
buf.Write(waitStr)
92+
buf.Write(lineStr)
93+
buf.Write(waitLink[i].holderStack.Bytes(" "))
94+
95+
buf.Write(goStr)
96+
buf.WriteString(strconv.Itoa(int(waitLink[i].monitor.holder)))
97+
buf.Write(holdStr)
98+
buf.Write(lineStr)
99+
buf.Write(waitLink[i].monitor.holderStack.Bytes(" "))
85100
}
86101
panic(DeadlockError(buf.String()))
87102
}
88103
// the lock holder is waiting for another lock
89-
if waitTarget, exists := waitTargets[m.holder]; exists {
90-
waitTarget.verify(append(holderLink, m))
104+
if waitInfo, exists := waitingList[m.holder]; exists {
105+
waitInfo.monitor.verify(append(waitLink, waitInfo))
91106
}
92107
}
93108
}
94109

95-
func (m *mointor) using(holder int32, holderStack debug.StackInfo) {
110+
func (m *monitor) using(waitInfo *waiting) {
96111
globalMutex.Lock()
97112
defer globalMutex.Unlock()
98113

99-
delete(waitTargets, holder)
100-
m.holder = holder
101-
m.holderStack = holderStack
114+
delete(waitingList, waitInfo.holder)
115+
m.holder = waitInfo.holder
116+
m.holderStack = waitInfo.holderStack
102117
}
103118

104-
func (m *mointor) release() {
119+
func (m *monitor) release() {
105120
m.holder = 0
106121
m.holderStack = nil
107122
}

0 commit comments

Comments
 (0)