Skip to content

Parallel tasks don't release terminal after completion — signal handler goroutine leak #177

@jpilier

Description

@jpilier

Description

When running parallel tasks (e.g., rr test with parallel: [test-backend, test-frontend]), the process does not return control to the terminal after all tasks complete successfully. The terminal appears to hang
indefinitely.

Single tasks (rr test-backend, rr test-frontend) work fine and exit cleanly.

Root Cause

RunParallelTask in /internal/cli/parallel.go (~line 186) registers a signal handler but never cleans it up:

sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
go func() {
<-sigChan
cancel()
}()

  • signal.Notify is called but signal.Stop is never called after execution completes
  • The goroutine blocks forever on <-sigChan since no signal arrives during normal execution
  • The active signal registration keeps Go's runtime intercepting SIGINT/SIGTERM instead of allowing default process termination

The non-parallel workflow path in /internal/cli/workflow.go handles this correctly:

func (w *WorkflowContext) Close() {
w.closeOnce.Do(func() {
signal.Stop(w.signalChan)
close(w.signalChan)
})
}

The same missing cleanup also exists in:

  • /internal/cli/run.go in runRepeated() (~line 419)
  • /internal/cli/task.go in runTaskRepeated() (~line 972)

Suggested Fix

Add signal.Stop and close after the orchestrator returns, matching the pattern in workflow.go:

result, err := orchestrator.Run(ctx)

signal.Stop(sigChan)
close(sigChan)

And update the goroutine to handle the closed channel:

go func() {
sig, ok := <-sigChan
if !ok {
return
}
_ = sig
cancel()
}()

Apply the same fix to run.go and task.go.

Reproduction

.rr.yaml:
hosts: [host-1, host-2]

tasks:
task-a:
run: echo "done A"
task-b:
run: echo "done B"
test:
parallel: [task-a, task-b]
fail_fast: false

rr test # hangs after both tasks complete

Environment

  • rr v0.19.0
  • macOS (Darwin 25.2.0)
  • Go 1.22+

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions