fix race condition on js.timer in scripts.d scheduler (#21801)
Ilya Mashchenko committed
Feb 22, 2026 at 22:31 UTC
b87f24b2238487d4f397a3a6e3768585f16d7600
1 file changed
+9
-3
src/go/plugin/scripts.d/pkg/runtime/scheduler.go
+9
-3
@@ -276,16 +276,20 @@ func (s *Scheduler) Stop() {
276
if s.cancel != nil {
277
s.cancel()
278
}
279
+ s.jobMu.Lock()
280
for _, js := range s.jobs {
281
if js.timer != nil {
282
js.timer.Stop()
283
js.timer = nil
284
}
285
}
286
+ s.jobMu.Unlock()
287
s.executor.Stop()
288
s.wg.Wait()
289
+ s.jobMu.Lock()
290
s.ctx = nil
291
s.cancel = nil
292
+ s.jobMu.Unlock()
293
}
294
295
func (s *Scheduler) run() {
@@ -410,7 +414,10 @@ func (s *Scheduler) handleResult(res ExecutionResult) {
414
}
415
416
func (s *Scheduler) armTimer(js *jobState) {
413
- if s.ctx == nil {
417
+ s.jobMu.Lock()
418
+ ctx := s.ctx
419
+ if ctx == nil {
420
+ s.jobMu.Unlock()
421
return
422
}
423
delay := time.Until(js.nextRun)
@@ -418,8 +425,6 @@ func (s *Scheduler) armTimer(js *jobState) {
425
delay = 0
426
}
427
jobID := js.runtime.ID
421
- ctx := s.ctx // capture to avoid racing with Stop() nilling s.ctx
422
-
428
if js.timer == nil {
429
js.timer = time.AfterFunc(delay, func() {
430
select {
@@ -430,6 +435,7 @@ func (s *Scheduler) armTimer(js *jobState) {
435
} else {
436
js.timer.Reset(delay)
437
}
438
+ s.jobMu.Unlock()
439
}
440
441
func (s *Scheduler) runJob(ctx context.Context, job JobRuntime) ExecutionResult {