Skip to content

Commit

Permalink
fxlog/spy: Eliminate data race (uber-go#790)
Browse files Browse the repository at this point in the history
It's possible that two goroutines are writing to fxlog.Spy
at the same time because Start/Stop hooks run in separate goroutines.

Resolve this race with the use of an RWMutex.
  • Loading branch information
abhinav committed Sep 17, 2021
1 parent c2cac45 commit 73030cd
Showing 1 changed file with 12 additions and 0 deletions.
12 changes: 12 additions & 0 deletions internal/fxlog/spy.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ package fxlog

import (
"reflect"
"sync"

"go.uber.org/fx/fxevent"
)
Expand All @@ -47,25 +48,34 @@ func (es Events) SelectByTypeName(name string) Events {
// Spy is an Fx event logger that captures emitted events and/or logged
// statements. It may be used in tests of Fx logs.
type Spy struct {
mu sync.RWMutex
events Events
}

var _ fxevent.Logger = &Spy{}

// LogEvent appends an Event.
func (s *Spy) LogEvent(event fxevent.Event) {
s.mu.Lock()
s.events = append(s.events, event)
s.mu.Unlock()
}

// Events returns all captured events.
func (s *Spy) Events() Events {
s.mu.RLock()
defer s.mu.RUnlock()

events := make(Events, len(s.events))
copy(events, s.events)
return events
}

// EventTypes returns all captured event types.
func (s *Spy) EventTypes() []string {
s.mu.RLock()
defer s.mu.RUnlock()

types := make([]string, len(s.events))
for i, e := range s.events {
types[i] = reflect.TypeOf(e).Elem().Name()
Expand All @@ -75,5 +85,7 @@ func (s *Spy) EventTypes() []string {

// Reset clears all messages and events from the Spy.
func (s *Spy) Reset() {
s.mu.Lock()
s.events = s.events[:0]
s.mu.Unlock()
}

0 comments on commit 73030cd

Please sign in to comment.