-
Notifications
You must be signed in to change notification settings - Fork 325
Closed
Labels
bugSomething isn't workingSomething isn't working
Description
Severity: HIGH
Bug Summary
The spinner.Suffix field is modified concurrently without synchronization when UpdateSpinnerMessage() is called from multiple goroutines, causing data races.
Location
- File: pkg/statushooks/spinner.go
- Function: UpdateSpinnerMessage() (line 111)
- Line: 113 -
s.spinner.Suffix = fmt.Sprintf(" %s", newMessage)
Reproduction
func TestSpinnerConcurrentUpdate(t *testing.T) {
spinner := NewStatusSpinnerHook()
spinner.Show()
defer spinner.Hide()
var wg sync.WaitGroup
for i := 0; i < 100; i++ {
wg.Add(1)
go func(n int) {
defer wg.Done()
spinner.UpdateSpinnerMessage(fmt.Sprintf("msg-%d", n))
}(i)
}
wg.Wait()
}Run with: go test -race ./pkg/statushooks/...
Evidence
Race detector shows:
- Write at spinner.Suffix in UpdateSpinnerMessage (line 113)
- Concurrent reads/writes from multiple goroutines
- Also races with Show() which reads spinner.Suffix (line 104)
Impact
- When: Multiple goroutines update status messages concurrently (common in parallel operations)
- Effect:
- Corrupted spinner messages
- Potential string corruption leading to garbled output
- Data race failures in tests
- Undefined behavior
Proposed Fix
Add mutex protection for spinner.Suffix modifications:
type StatusSpinner struct {
spinner *spinner.Spinner
cancel chan struct{}
delay time.Duration
visible bool
mu sync.RWMutex // Add mutex
}
func (s *StatusSpinner) UpdateSpinnerMessage(newMessage string) {
newMessage = s.truncateSpinnerMessageToScreen(newMessage)
s.mu.Lock()
s.spinner.Suffix = fmt.Sprintf(" %s", newMessage)
visible := s.visible
active := s.spinner.Active()
s.mu.Unlock()
if visible && !active {
s.spinner.Start()
}
}Found by: Wave 3 Task 1 (Statushooks)
Test: TestSpinnerConcurrentUpdate in pkg/statushooks/statushooks_test.go
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working