Tags: modu-ai/mink
Tags
hotfix(scheduler): Stop() 동시성 sync.Mutex 보호 (W1, v0.2.2) (#146) REVIEW-SCHEDULER-001-2026-05-10 W1 — Stop() 동시 호출 시 close-on-closed-channel panic + s.cron 무보호 포인터 race 수정. ## Reproduction (fix 전 캡처, count=20 -race) panic: close of closed channel goroutine 38 [running]: github.com/modu-ai/goose/internal/ritual/scheduler.(*Scheduler).Stop(...) scheduler.go:349 +0x158 github.com/modu-ai/goose/internal/ritual/scheduler_test.TestStop_ConcurrentCalls_Safe.func1() scheduler_test.go:1350 +0x8c scheduler.go:349 = close(s.workerDone). 기존 select { case <-workerDone: / default: close(workerDone) } 가드는 두 goroutine이 동시에 default 분기로 진입할 수 있어 double-close panic. ## Fix - Scheduler 구조체에 mu sync.Mutex 추가 (lifecycle 직렬화) - Start()/Stop() 진입부 mutex lock + idempotent state 체크 - Stop(): state != Running이면 즉시 return (idempotent guard) - close(workerDone) 가드 패턴 제거 (mutex 단일 진입 보장) - s.cron 포인터도 mutex 보호 (atomic.Pointer 불필요) - @mx:WARN 태그 추가 (lifecycle mutex 주의사항) ## 검증 - TestStop_ConcurrentCalls_Safe (count=10, -race): PASS - TestStartStop_NoRace (count=10, -race): PASS - full suite (count=1, -race): PASS (9.607s) - full suite stress (count=10, -race): PASS (91.48s) - go vet: PASS, gofmt: clean ## 변경 파일 (2개, +129 / -9) - internal/ritual/scheduler/scheduler.go: mu mutex + Stop() 재작성 - internal/ritual/scheduler/scheduler_test.go: 50/20 goroutine reproduction tests 추가 (Go 1.25+ wg.Go 패턴) SPEC: SPEC-GOOSE-SCHEDULER-001 REQ: REQ-SCHED-018 (graceful shutdown) 출처: REVIEW-SCHEDULER-001-2026-05-10 W1 🗿 MoAI <email@mo.ai.kr>