Skip to content

Commit c7e9f99

Browse files
peerless1024evelynwei
andauthored
fix: Go interface trap of underlying value is nil (#261)
* fix: CircuitBreakerAPI.Report stat param should not be nil (#258) Co-authored-by: evelynwei <[email protected]> * fix: Go interface trap of underlying value is nil (#260) Co-authored-by: evelynwei <[email protected]> --------- Co-authored-by: evelynwei <[email protected]>
1 parent 40517f5 commit c7e9f99

File tree

1 file changed

+36
-1
lines changed

1 file changed

+36
-1
lines changed

plugin/circuitbreaker/composite/breaker.go

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package composite
1919

2020
import (
2121
"context"
22+
"reflect"
2223
"sync"
2324
"sync/atomic"
2425
"time"
@@ -178,15 +179,49 @@ func (c *CompositeCircuitBreaker) Report(stat *model.ResourceStat) error {
178179
}
179180

180181
func (c *CompositeCircuitBreaker) doReport(stat *model.ResourceStat, record bool) error {
182+
// 第一层:检查 stat 是否为 nil
183+
if stat == nil {
184+
c.log.Errorf("[CircuitBreaker] doReport failed: stat is nil")
185+
return nil
186+
}
187+
// 第二层:检查 stat.Resource 接口是否为 nil
188+
if stat.Resource == nil {
189+
c.log.Errorf("[CircuitBreaker] doReport failed: stat.Resource is nil, stat=%+v", stat)
190+
return nil
191+
}
181192
resource := stat.Resource
182-
if resource == nil || resource.GetLevel() == fault_tolerance.Level_UNKNOWN {
193+
// 第三层:使用反射检查接口底层值是否为 nil(避免 Go 接口陷阱)
194+
rv := reflect.ValueOf(resource)
195+
if !rv.IsValid() {
196+
c.log.Errorf("[CircuitBreaker] doReport failed: resource reflect value is invalid, resource type=%T", resource)
197+
return nil
198+
}
199+
if rv.IsNil() {
200+
c.log.Errorf("[CircuitBreaker] doReport failed: resource underlying value is nil (Go interface trap), "+
201+
"resource type=%T", resource)
183202
return nil
184203
}
204+
// 第四层:检查 Service 是否为 nil
205+
service := resource.GetService()
206+
if service == nil {
207+
c.log.Errorf("[CircuitBreaker] doReport failed: resource.GetService() returns nil, resource=%s, level=%v",
208+
resource.String(), resource.GetLevel())
209+
return nil
210+
}
211+
// 第五层:检查 Level 是否有效
212+
level := resource.GetLevel()
213+
if level == fault_tolerance.Level_UNKNOWN {
214+
c.log.Errorf("[CircuitBreaker] doReport failed: resource level is UNKNOWN, resource=%s, service=%s",
215+
resource.String(), service.String())
216+
return nil
217+
}
218+
185219
retStatus := stat.RetStatus
186220
// 因为限流、熔断被拒绝的请求,不需要进入熔断数据上报
187221
if retStatus == model.RetReject || retStatus == model.RetFlowControl {
188222
return nil
189223
}
224+
190225
counters, exist := c.getResourceCounters(resource)
191226
if !exist {
192227
c.containers.LoadOrStore(resource.String(), newRuleContainer(c.taskCtx, resource, c))

0 commit comments

Comments
 (0)