Skip to content

Commit 38d8d88

Browse files
committed
fix bug
1 parent 660b7fc commit 38d8d88

File tree

1 file changed

+62
-58
lines changed

1 file changed

+62
-58
lines changed

deadlock.go

Lines changed: 62 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func (m *RWMutex) RUnlock() {
5656

5757
var (
5858
globalMutex = new(sync.Mutex)
59-
waitingList = make(map[int32]*waiting)
59+
waitingList = make(map[int32]*lockUsage)
6060
titleStr = []byte("[DEAD LOCK]\n")
6161
goStr = []byte("goroutine ")
6262
waitStr = []byte(" wait")
@@ -66,101 +66,105 @@ var (
6666
lineStr = []byte{'\n'}
6767
)
6868

69-
type waiting struct {
70-
monitor *monitor
71-
mode byte
72-
holder int32
73-
holderStack debug.StackInfo
69+
type lockUsage struct {
70+
monitor *monitor
71+
mode byte
72+
goid int32
73+
stack debug.StackInfo
7474
}
7575

7676
type monitor struct {
7777
holders *list.List
7878
}
7979

80-
func (m *monitor) wait(mode byte) *waiting {
80+
func (m *monitor) wait(mode byte) *lockUsage {
8181
globalMutex.Lock()
8282
defer globalMutex.Unlock()
8383

84-
waitInfo := &waiting{m, mode, goid.Get(), debug.StackTrace(3, 0)}
85-
waitingList[waitInfo.holder] = waitInfo
84+
waitInfo := &lockUsage{m, mode, goid.Get(), debug.StackTrace(3, 0)}
85+
waitingList[waitInfo.goid] = waitInfo
8686

8787
if m.holders == nil {
8888
m.holders = list.New()
8989
}
9090

91-
m.verify(mode, []*waiting{waitInfo})
91+
m.diagnose(mode, []*lockUsage{waitInfo})
9292

9393
return waitInfo
9494
}
9595

96-
func (m *monitor) verify(mode byte, waitLink []*waiting) {
96+
func (m *monitor) diagnose(mode byte, waitLink []*lockUsage) {
9797
for i := m.holders.Front(); i != nil; i = i.Next() {
98-
holder := i.Value.(*waiting)
98+
holder := i.Value.(*lockUsage)
9999
if mode != 'r' || holder.mode != 'r' {
100100
// deadlock detected
101-
if holder.holder == waitLink[0].holder {
102-
buf := new(bytes.Buffer)
103-
buf.Write(titleStr)
104-
for i := 0; i < len(waitLink); i++ {
105-
buf.Write(goStr)
106-
buf.WriteString(strconv.Itoa(int(waitLink[i].holder)))
107-
buf.Write(waitStr)
108-
if waitLink[i].mode == 'w' {
109-
buf.Write(writeStr)
110-
} else {
111-
buf.Write(readStr)
112-
}
113-
buf.Write(lineStr)
114-
buf.Write(waitLink[i].holderStack.Bytes(" "))
115-
116-
// lookup waiting for who
117-
n := i + 1
118-
if n == len(waitLink) {
119-
n = 0
120-
}
121-
waitWho := waitLink[n]
122-
123-
for j := waitLink[i].monitor.holders.Front(); j != nil; j = j.Next() {
124-
waitHolder := j.Value.(*waiting)
125-
if waitHolder.holder == waitWho.holder {
126-
buf.Write(goStr)
127-
buf.WriteString(strconv.Itoa(int(waitHolder.holder)))
128-
buf.Write(holdStr)
129-
if waitHolder.mode == 'w' {
130-
buf.Write(writeStr)
131-
} else {
132-
buf.Write(readStr)
133-
}
134-
buf.Write(lineStr)
135-
buf.Write(waitHolder.holderStack.Bytes(" "))
136-
break
137-
}
138-
}
139-
}
140-
panic(DeadlockError(buf.String()))
101+
if holder.goid == waitLink[0].goid {
102+
deadlockPanic(waitLink)
141103
}
142104
// the lock holder is waiting for another lock
143-
if waitInfo, exists := waitingList[holder.holder]; exists {
144-
waitInfo.monitor.verify(waitInfo.mode, append(waitLink, waitInfo))
105+
if waitInfo, exists := waitingList[holder.goid]; exists {
106+
waitInfo.monitor.diagnose(waitInfo.mode, append(waitLink, waitInfo))
145107
}
146108
}
147109
}
148110
}
149111

150-
func (m *monitor) using(waitInfo *waiting) {
112+
func (m *monitor) using(waitInfo *lockUsage) {
151113
globalMutex.Lock()
152114
defer globalMutex.Unlock()
153115

154-
delete(waitingList, waitInfo.holder)
116+
delete(waitingList, waitInfo.goid)
155117
m.holders.PushBack(waitInfo)
156118
}
157119

158120
func (m *monitor) release(mode byte) {
159-
holder := goid.Get()
121+
id := goid.Get()
160122
for i := m.holders.Back(); i != nil; i = i.Prev() {
161-
if info := i.Value.(*waiting); info.holder == holder && info.mode == mode {
123+
if info := i.Value.(*lockUsage); info.goid == id && info.mode == mode {
162124
m.holders.Remove(i)
163125
break
164126
}
165127
}
166128
}
129+
130+
func deadlockPanic(waitLink []*lockUsage) {
131+
buf := new(bytes.Buffer)
132+
buf.Write(titleStr)
133+
for i := 0; i < len(waitLink); i++ {
134+
buf.Write(goStr)
135+
buf.WriteString(strconv.Itoa(int(waitLink[i].goid)))
136+
buf.Write(waitStr)
137+
if waitLink[i].mode == 'w' {
138+
buf.Write(writeStr)
139+
} else {
140+
buf.Write(readStr)
141+
}
142+
buf.Write(lineStr)
143+
buf.Write(waitLink[i].stack.Bytes(" "))
144+
145+
// lookup waiting for who
146+
n := i + 1
147+
if n == len(waitLink) {
148+
n = 0
149+
}
150+
waitWho := waitLink[n]
151+
152+
for j := waitLink[i].monitor.holders.Front(); j != nil; j = j.Next() {
153+
waitHolder := j.Value.(*lockUsage)
154+
if waitHolder.goid == waitWho.goid {
155+
buf.Write(goStr)
156+
buf.WriteString(strconv.Itoa(int(waitHolder.goid)))
157+
buf.Write(holdStr)
158+
if waitHolder.mode == 'w' {
159+
buf.Write(writeStr)
160+
} else {
161+
buf.Write(readStr)
162+
}
163+
buf.Write(lineStr)
164+
buf.Write(waitHolder.stack.Bytes(" "))
165+
break
166+
}
167+
}
168+
}
169+
panic(DeadlockError(buf.String()))
170+
}

0 commit comments

Comments
 (0)