Skip to content

Commit e48a6ef

Browse files
authored
Fix slot chain dead lock bug and deprecated resource slot chain (#379)
1 parent f854c93 commit e48a6ef

23 files changed

+1
-681
lines changed

api/api.go

+1-5
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818
"sync"
1919

2020
"github.com/alibaba/sentinel-golang/core/base"
21-
"github.com/alibaba/sentinel-golang/core/misc"
2221
)
2322

2423
var entryOptsPool = sync.Pool{
@@ -142,10 +141,7 @@ func Entry(resource string, opts ...EntryOption) (*base.SentinelEntry, *base.Blo
142141
opt(options)
143142
}
144143
if options.slotChain == nil {
145-
options.slotChain = misc.GetResourceSlotChain(resource)
146-
if options.slotChain == nil {
147-
options.slotChain = GlobalSlotChain()
148-
}
144+
options.slotChain = GlobalSlotChain()
149145
}
150146
return entry(resource, options)
151147
}

api/api_test.go

-16
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,6 @@ type prepareSlotMock struct {
2626
mock.Mock
2727
}
2828

29-
func (m *prepareSlotMock) Name() string {
30-
return "mock-sentinel-prepare-slot"
31-
}
32-
3329
func (m *prepareSlotMock) Order() uint32 {
3430
return 0
3531
}
@@ -43,10 +39,6 @@ type mockRuleCheckSlot1 struct {
4339
mock.Mock
4440
}
4541

46-
func (m *mockRuleCheckSlot1) Name() string {
47-
return "mock-sentinel-rule-check-slot1"
48-
}
49-
5042
func (m *mockRuleCheckSlot1) Order() uint32 {
5143
return 0
5244
}
@@ -60,10 +52,6 @@ type mockRuleCheckSlot2 struct {
6052
mock.Mock
6153
}
6254

63-
func (m *mockRuleCheckSlot2) Name() string {
64-
return "mock-sentinel-rule-check-slot2"
65-
}
66-
6755
func (m *mockRuleCheckSlot2) Order() uint32 {
6856
return 0
6957
}
@@ -77,10 +65,6 @@ type statisticSlotMock struct {
7765
mock.Mock
7866
}
7967

80-
func (m *statisticSlotMock) Name() string {
81-
return "mock-sentinel-stat-check-slot"
82-
}
83-
8468
func (m *statisticSlotMock) Order() uint32 {
8569
return 0
8670
}

api/slot_chain.go

-19
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121
"github.com/alibaba/sentinel-golang/core/hotspot"
2222
"github.com/alibaba/sentinel-golang/core/isolation"
2323
"github.com/alibaba/sentinel-golang/core/log"
24-
"github.com/alibaba/sentinel-golang/core/misc"
2524
"github.com/alibaba/sentinel-golang/core/stat"
2625
"github.com/alibaba/sentinel-golang/core/system"
2726
)
@@ -49,21 +48,3 @@ func BuildDefaultSlotChain() *base.SlotChain {
4948
sc.AddStatSlot(circuitbreaker.DefaultMetricStatSlot)
5049
return sc
5150
}
52-
53-
// RegisterGlobalStatPrepareSlot registers the global StatPrepareSlot for all resource
54-
// Note: this function is not thread-safe
55-
func RegisterGlobalStatPrepareSlot(slot base.StatPrepareSlot) {
56-
misc.RegisterGlobalStatPrepareSlot(slot)
57-
}
58-
59-
// RegisterGlobalRuleCheckSlot registers the global RuleCheckSlot for all resource
60-
// Note: this function is not thread-safe
61-
func RegisterGlobalRuleCheckSlot(slot base.RuleCheckSlot) {
62-
misc.RegisterGlobalRuleCheckSlot(slot)
63-
}
64-
65-
// RegisterGlobalStatSlot registers the global StatSlot for all resource
66-
// Note: this function is not thread-safe
67-
func RegisterGlobalStatSlot(slot base.StatSlot) {
68-
misc.RegisterGlobalStatSlot(slot)
69-
}

core/base/slot_chain.go

-86
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@ import (
2424
)
2525

2626
type BaseSlot interface {
27-
// Name returns it's slot name which should be global unique.
28-
Name() string
29-
3027
// Order returns the sort value of the slot.
3128
// SlotChain will sort all it's slots by ascending sort value in each bucket
3229
// (StatPrepareSlot bucket、RuleCheckSlot bucket and StatSlot bucket)
@@ -77,8 +74,6 @@ type StatSlot interface {
7774
// SlotChain hold all system slots and customized slot.
7875
// SlotChain support plug-in slots developed by developer.
7976
type SlotChain struct {
80-
// RWMutex guard the slots in SlotChain and make sure the concurrency safe
81-
sync.RWMutex
8277
// statPres is in ascending order by StatPrepareSlot.Order() value.
8378
statPres []StatPrepareSlot
8479
// ruleChecks is in ascending order by RuleCheckSlot.Order() value.
@@ -108,7 +103,6 @@ var (
108103

109104
func NewSlotChain() *SlotChain {
110105
return &SlotChain{
111-
RWMutex: sync.RWMutex{},
112106
statPres: make([]StatPrepareSlot, 0, 8),
113107
ruleChecks: make([]RuleCheckSlot, 0, 8),
114108
stats: make([]StatSlot, 0, 8),
@@ -130,31 +124,6 @@ func (sc *SlotChain) RefurbishContext(c *EntryContext) {
130124
}
131125
}
132126

133-
// ValidateStatPrepareSlotNaming checks whether the name of StatPrepareSlot exists in SlotChain.[]StatPrepareSlot
134-
// return true the name of StatPrepareSlot doesn't exist in SlotChain.[]StatPrepareSlot
135-
// ValidateStatPrepareSlotNaming is non-thread safe,
136-
// In concurrency scenario, ValidateStatPrepareSlotNaming must be guarded by SlotChain.RWMutex#RLock
137-
func ValidateStatPrepareSlotNaming(sc *SlotChain, s StatPrepareSlot) bool {
138-
isValid := true
139-
f := func(slot StatPrepareSlot) {
140-
if slot.Name() == s.Name() {
141-
isValid = false
142-
}
143-
}
144-
sc.RangeStatPrepareSlot(f)
145-
146-
return isValid
147-
}
148-
149-
// RangeStatPrepareSlot iterates the SlotChain.[]StatPrepareSlot and call f function for each StatPrepareSlot
150-
// RangeStatPrepareSlot is non-thread safe,
151-
// In concurrency scenario, RangeStatPrepareSlot must be guarded by SlotChain.RWMutex#RLock
152-
func (sc *SlotChain) RangeStatPrepareSlot(f func(slot StatPrepareSlot)) {
153-
for _, slot := range sc.statPres {
154-
f(slot)
155-
}
156-
}
157-
158127
// AddStatPrepareSlot adds the StatPrepareSlot slot to the StatPrepareSlot list of the SlotChain.
159128
// All StatPrepareSlot in the list will be sorted according to StatPrepareSlot.Order() in ascending order.
160129
// AddStatPrepareSlot is non-thread safe,
@@ -166,31 +135,6 @@ func (sc *SlotChain) AddStatPrepareSlot(s StatPrepareSlot) {
166135
})
167136
}
168137

169-
// ValidateRuleCheckSlotNaming checks whether the name of RuleCheckSlot exists in SlotChain.[]RuleCheckSlot
170-
// return true the name of RuleCheckSlot doesn't exist in SlotChain.[]RuleCheckSlot
171-
// ValidateRuleCheckSlotNaming is non-thread safe,
172-
// In concurrency scenario, ValidateRuleCheckSlotNaming must be guarded by SlotChain.RWMutex#RLock
173-
func ValidateRuleCheckSlotNaming(sc *SlotChain, s RuleCheckSlot) bool {
174-
isValid := true
175-
f := func(slot RuleCheckSlot) {
176-
if slot.Name() == s.Name() {
177-
isValid = false
178-
}
179-
}
180-
sc.RangeRuleCheckSlot(f)
181-
182-
return isValid
183-
}
184-
185-
// RangeRuleCheckSlot iterates the SlotChain.[]RuleCheckSlot and call f function for each RuleCheckSlot
186-
// RangeRuleCheckSlot is non-thread safe,
187-
// In concurrency scenario, RangeRuleCheckSlot must be guarded by SlotChain.RWMutex#RLock
188-
func (sc *SlotChain) RangeRuleCheckSlot(f func(slot RuleCheckSlot)) {
189-
for _, slot := range sc.ruleChecks {
190-
f(slot)
191-
}
192-
}
193-
194138
// AddRuleCheckSlot adds the RuleCheckSlot to the RuleCheckSlot list of the SlotChain.
195139
// All RuleCheckSlot in the list will be sorted according to RuleCheckSlot.Order() in ascending order.
196140
// AddRuleCheckSlot is non-thread safe,
@@ -202,31 +146,6 @@ func (sc *SlotChain) AddRuleCheckSlot(s RuleCheckSlot) {
202146
})
203147
}
204148

205-
// ValidateStatSlotNaming checks whether the name of StatSlot exists in SlotChain.[]StatSlot
206-
// return true the name of StatSlot doesn't exist in SlotChain.[]StatSlot
207-
// ValidateStatSlotNaming is non-thread safe,
208-
// In concurrency scenario, ValidateStatSlotNaming must be guarded by SlotChain.RWMutex#RLock
209-
func ValidateStatSlotNaming(sc *SlotChain, s StatSlot) bool {
210-
isValid := true
211-
f := func(slot StatSlot) {
212-
if slot.Name() == s.Name() {
213-
isValid = false
214-
}
215-
}
216-
sc.RangeStatSlot(f)
217-
218-
return isValid
219-
}
220-
221-
// RangeStatSlot iterates the SlotChain.[]StatSlot and call f function for each StatSlot
222-
// RangeStatSlot is non-thread safe,
223-
// In concurrency scenario, RangeStatSlot must be guarded by SlotChain.RWMutex#RLock
224-
func (sc *SlotChain) RangeStatSlot(f func(slot StatSlot)) {
225-
for _, slot := range sc.stats {
226-
f(slot)
227-
}
228-
}
229-
230149
// AddStatSlot adds the StatSlot to the StatSlot list of the SlotChain.
231150
// All StatSlot in the list will be sorted according to StatSlot.Order() in ascending order.
232151
// AddStatSlot is non-thread safe,
@@ -241,11 +160,9 @@ func (sc *SlotChain) AddStatSlot(s StatSlot) {
241160
// The entrance of slot chain
242161
// Return the TokenResult and nil if internal panic.
243162
func (sc *SlotChain) Entry(ctx *EntryContext) *TokenResult {
244-
sc.RLock()
245163
// This should not happen, unless there are errors existing in Sentinel internal.
246164
// If happened, need to add TokenResult in EntryContext
247165
defer func() {
248-
sc.RUnlock()
249166
if err := recover(); err != nil {
250167
logging.Error(errors.Errorf("%+v", err), "Sentinel internal panic in SlotChain.Entry()")
251168
ctx.SetError(errors.Errorf("%+v", err))
@@ -311,9 +228,6 @@ func (sc *SlotChain) exit(ctx *EntryContext) {
311228
if ctx.IsBlocked() {
312229
return
313230
}
314-
315-
sc.RLock()
316-
defer sc.RUnlock()
317231
for _, s := range sc.stats {
318232
s.OnCompleted(ctx)
319233
}

0 commit comments

Comments
 (0)