Skip to content

Commit a7e2846

Browse files
fix: fix race conditions in the recorder.go file
1 parent 9491d53 commit a7e2846

File tree

1 file changed

+58
-16
lines changed

1 file changed

+58
-16
lines changed

recorder.go

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,30 @@ type Recorder struct {
3232
func NewRecorder() *Recorder {
3333
r := &Recorder{}
3434

35-
ticker := time.NewTicker(1 * time.Second)
35+
// Create a reference to r that will be captured by the goroutine
36+
recorder := r
37+
3638
go func() {
39+
ticker := time.NewTicker(1 * time.Second)
40+
defer ticker.Stop() // Ensure ticker is stopped when goroutine exits
41+
3742
for range ticker.C {
38-
if sensor.Agent().Ready() {
39-
go func() {
40-
if err := r.Flush(context.Background()); err != nil {
41-
sensor.logger.Error("failed to flush the spans: ", err.Error())
43+
muSensor.Lock()
44+
agentReady := sensor != nil && sensor.Agent().Ready()
45+
muSensor.Unlock()
46+
47+
if agentReady {
48+
// Create a new reference to recorder for this goroutine to avoid race conditions
49+
r := recorder
50+
go func(rec *Recorder) {
51+
if err := rec.Flush(context.Background()); err != nil {
52+
muSensor.Lock()
53+
if sensor != nil {
54+
sensor.logger.Error("failed to flush the spans: ", err.Error())
55+
}
56+
muSensor.Unlock()
4257
}
43-
}()
58+
}(r)
4459
}
4560
}
4661
}()
@@ -59,32 +74,51 @@ func NewTestRecorder() *Recorder {
5974
// RecordSpan accepts spans to be recorded and added to the span queue
6075
// for eventual reporting to the host agent.
6176
func (r *Recorder) RecordSpan(span *spanS) {
77+
// Get all sensor-related values under a single lock to minimize contention
78+
muSensor.Lock()
79+
if sensor == nil {
80+
muSensor.Unlock()
81+
return
82+
}
83+
84+
agentReady := sensor.Agent().Ready()
85+
maxBufferedSpans := sensor.options.MaxBufferedSpans
86+
forceTransmissionAt := sensor.options.ForceTransmissionStartingAt
87+
logger := sensor.logger
88+
muSensor.Unlock()
89+
6290
// If we're not announced and not in test mode then just
6391
// return
64-
if !r.testMode && !sensor.Agent().Ready() {
92+
if !r.testMode && !agentReady {
6593
return
6694
}
6795

6896
r.Lock()
6997
defer r.Unlock()
7098

71-
if len(r.spans) == sensor.options.MaxBufferedSpans {
99+
if len(r.spans) == maxBufferedSpans {
72100
r.spans = r.spans[1:]
73101
}
74102

75103
r.spans = append(r.spans, newSpan(span))
76104

77-
if r.testMode || !sensor.Agent().Ready() {
105+
if r.testMode || !agentReady {
78106
return
79107
}
80108

81-
if len(r.spans) >= sensor.options.ForceTransmissionStartingAt {
82-
sensor.logger.Debug("forcing ", len(r.spans), "span(s) to the agent")
83-
go func() {
84-
if err := r.Flush(context.Background()); err != nil {
85-
sensor.logger.Error("failed to flush the spans: ", err.Error())
109+
if len(r.spans) >= forceTransmissionAt {
110+
logger.Debug("forcing ", len(r.spans), "span(s) to the agent")
111+
// Create a reference to r for this goroutine to avoid race conditions
112+
rec := r
113+
go func(recorder *Recorder) {
114+
if err := recorder.Flush(context.Background()); err != nil {
115+
muSensor.Lock()
116+
if sensor != nil {
117+
sensor.logger.Error("failed to flush the spans: ", err.Error())
118+
}
119+
muSensor.Unlock()
86120
}
87-
}()
121+
}(rec)
88122
}
89123
}
90124

@@ -118,7 +152,15 @@ func (r *Recorder) Flush(ctx context.Context) error {
118152
return nil
119153
}
120154

121-
if err := sensor.Agent().SendSpans(spansToSend); err != nil {
155+
muSensor.Lock()
156+
if sensor == nil {
157+
muSensor.Unlock()
158+
return nil
159+
}
160+
agent := sensor.Agent()
161+
muSensor.Unlock()
162+
163+
if err := agent.SendSpans(spansToSend); err != nil {
122164
r.Lock()
123165
defer r.Unlock()
124166

0 commit comments

Comments
 (0)