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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy