fix(test): resolve data race on forceKillDelay with atomic operations

Replace global int variable with atomic.Int32 to eliminate race condition detected in TestRunForwardSignals. Concurrent reads in forwardSignals/terminateProcess goroutines now use Load(), tests use Store().

Test results: all 100+ tests pass with -race enabled.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
freespace8
2025-12-07 17:12:52 +08:00
parent 85303126d6
commit 9452b77307
2 changed files with 13 additions and 8 deletions

View File

@@ -41,12 +41,17 @@ var (
buildCodexArgsFn = buildCodexArgs
commandContext = exec.CommandContext
jsonMarshal = json.Marshal
forceKillDelay = 5 // seconds - made variable for testability
cleanupLogsFn = cleanupOldLogs
signalNotifyFn = signal.Notify
signalStopFn = signal.Stop
)
var forceKillDelay atomic.Int32
func init() {
forceKillDelay.Store(5) // seconds - default value
}
// Config holds CLI configuration
type Config struct {
Mode string // "new" or "resume"
@@ -998,7 +1003,7 @@ func forwardSignals(ctx context.Context, cmd *exec.Cmd, logErrorFn func(string))
return
}
_ = cmd.Process.Signal(syscall.SIGTERM)
time.AfterFunc(time.Duration(forceKillDelay)*time.Second, func() {
time.AfterFunc(time.Duration(forceKillDelay.Load())*time.Second, func() {
if cmd.Process != nil {
_ = cmd.Process.Kill()
}
@@ -1032,7 +1037,7 @@ func terminateProcess(cmd *exec.Cmd) *time.Timer {
_ = cmd.Process.Signal(syscall.SIGTERM)
return time.AfterFunc(time.Duration(forceKillDelay)*time.Second, func() {
return time.AfterFunc(time.Duration(forceKillDelay.Load())*time.Second, func() {
if cmd.Process != nil {
_ = cmd.Process.Kill()
}

View File

@@ -33,7 +33,7 @@ func resetTestHooks() {
buildCodexArgsFn = buildCodexArgs
commandContext = exec.CommandContext
jsonMarshal = json.Marshal
forceKillDelay = 5
forceKillDelay.Store(5)
closeLogger()
}
@@ -1530,7 +1530,7 @@ func TestRun_LoggerRemovedOnSignal(t *testing.T) {
defer signal.Reset(syscall.SIGINT, syscall.SIGTERM)
// Set shorter delays for faster test
forceKillDelay = 1
forceKillDelay.Store(1)
tempDir := t.TempDir()
t.Setenv("TMPDIR", tempDir)
@@ -1762,12 +1762,12 @@ func TestRunForwardSignals(t *testing.T) {
cmd.Wait()
}()
forceKillDelay = 0
defer func() { forceKillDelay = 5 }()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
forceKillDelay.Store(0)
defer forceKillDelay.Store(5)
ready := make(chan struct{})
var captured chan<- os.Signal
signalNotifyFn = func(ch chan<- os.Signal, sig ...os.Signal) {