Skip to content

Commit bc3eca4

Browse files
Fix data race issue in globalShadowMode variable (#370)
globalShadowMode is written when config is reloaded and read in here, which may lead to data race condition Signed-off-by: Renuka Fernando <[email protected]>
1 parent 0b2f4d5 commit bc3eca4

File tree

2 files changed

+8
-8
lines changed

2 files changed

+8
-8
lines changed

src/service/ratelimit.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ var tracer = otel.Tracer("ratelimit")
3232

3333
type RateLimitServiceServer interface {
3434
pb.RateLimitServiceServer
35-
GetCurrentConfig() config.RateLimitConfig
35+
GetCurrentConfig() (config.RateLimitConfig, bool)
3636
}
3737

3838
type service struct {
@@ -107,8 +107,7 @@ func checkServiceErr(something bool, msg string) {
107107
}
108108
}
109109

110-
func (this *service) constructLimitsToCheck(request *pb.RateLimitRequest, ctx context.Context) ([]*config.RateLimit, []bool) {
111-
snappedConfig := this.GetCurrentConfig()
110+
func (this *service) constructLimitsToCheck(request *pb.RateLimitRequest, ctx context.Context, snappedConfig config.RateLimitConfig) ([]*config.RateLimit, []bool) {
112111
checkServiceErr(snappedConfig != nil, "no rate limit configuration loaded")
113112

114113
limitsToCheck := make([]*config.RateLimit, len(request.Descriptors))
@@ -180,7 +179,8 @@ func (this *service) shouldRateLimitWorker(
180179
checkServiceErr(request.Domain != "", "rate limit domain must not be empty")
181180
checkServiceErr(len(request.Descriptors) != 0, "rate limit descriptor list must not be empty")
182181

183-
limitsToCheck, isUnlimited := this.constructLimitsToCheck(request, ctx)
182+
snappedConfig, globalShadowMode := this.GetCurrentConfig()
183+
limitsToCheck, isUnlimited := this.constructLimitsToCheck(request, ctx, snappedConfig)
184184

185185
responseDescriptorStatuses := this.cache.DoLimit(ctx, request, limitsToCheck)
186186
assert.Assert(len(limitsToCheck) == len(responseDescriptorStatuses))
@@ -228,7 +228,7 @@ func (this *service) shouldRateLimitWorker(
228228
}
229229

230230
// If there is a global shadow_mode, it should always return OK
231-
if finalCode == pb.RateLimitResponse_OVER_LIMIT && this.globalShadowMode {
231+
if finalCode == pb.RateLimitResponse_OVER_LIMIT && globalShadowMode {
232232
finalCode = pb.RateLimitResponse_OK
233233
this.stats.GlobalShadowMode.Inc()
234234
}
@@ -306,10 +306,10 @@ func (this *service) ShouldRateLimit(
306306
return response, nil
307307
}
308308

309-
func (this *service) GetCurrentConfig() config.RateLimitConfig {
309+
func (this *service) GetCurrentConfig() (config.RateLimitConfig, bool) {
310310
this.configLock.RLock()
311311
defer this.configLock.RUnlock()
312-
return this.config
312+
return this.config, this.globalShadowMode
313313
}
314314

315315
func NewService(runtime loader.IFace, cache limiter.RateLimitCache,

src/service_cmd/runner/runner.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ func (runner *Runner) Run() {
130130
"/rlconfig",
131131
"print out the currently loaded configuration for debugging",
132132
func(writer http.ResponseWriter, request *http.Request) {
133-
if current := service.GetCurrentConfig(); current != nil {
133+
if current, _ := service.GetCurrentConfig(); current != nil {
134134
io.WriteString(writer, current.Dump())
135135
}
136136
})

0 commit comments

Comments
 (0)