elastic / elastic/beats

[bug-hunter] Data race in internal/otel/sharedcomponent Component.Start

Open
#50,035 3 comments 0 reactions 0 assignees View on GitHub
Team:Elastic-Agent-Data-Plane
Dominant language
Go
Stars
12.7k
Forks
5k
Avg merge
2d 15m
Merged PRs (30d)
385

Description

## Impact
Users running OpenTelemetry components with shared component startup across concurrent pipelines can hit a data race in `Component.Start`, which can lead to undefined behavior and startup instability under concurrent starts.

## Reproduction Steps
1. Create `internal/otel/sharedcomponent/race_repro_test.go` with the test below.
2. Run:
```bash
go test -race ./internal/otel/sharedcomponent -run TestStartConcurrentRaceRepro -count=1
```

## Expected vs Actual
**Expected:** `go test -race` passes without race warnings.

**Actual:** `go test -race` fails with a race warning between read/write of `c.hostWrapper`:

```text
WARNING: DATA RACE
Write at ... sharedcomponent.go:108 ...
Previous read at ... sharedcomponent.go:105 ...
--- FAIL: TestStartConcurrentRaceRepro
testing.go:1617: race detected during execution of test
FAIL
```

## Failing Test
```go
package sharedcomponent

import (
"context"
"sync"
"testing"

"github.com/stretchr/testify/require"
"go.opentelemetry.io/collector/component"
"go.opentelemetry.io/collector/component/componenttest"
)

type noopComponent struct{}

func (n *noopComponent) Start(_ context.Context, _ component.Host) error { return nil }
func (n *noopComponent) Shutdown(_ context.Context) error { return nil }

func TestStartConcurrentRaceRepro(t *testing.T) {
t.Parallel()

const attempts = 400
for i := 0; i < attempts; i++ {
shared := &Component[component.Component]{
component: &noopComponent{},
removeFunc: func() {},
}

start := make(chan struct{})
var wg sync.WaitGroup
wg.Add(2)
errs := make(chan error, 2)
host := componenttest.NewNopHost()

for range 2 {
go func() {
defer wg.Done()
<-start
errs <- shared.Start(t.Context(), host)
}()
}

close(start)
wg.Wait()
close(errs)

for err := range errs {
require.NoError(t, err, "shared component Start should not return an error in race repro")
}
}
}
```

## Evidence
- Unsynchronized read/write in `Start`:
- `internal/otel/sharedcomponent/sharedcomponent.go:105` reads `if c.hostWrapper == nil`
- `internal/otel/sharedcomponent/sharedcomponent.go:108` writes `c.hostWrapper = &hostWrapper{...}` inside `startOnce.Do`
- The race detector output points directly to those lines during concurrent `Start` calls.

A synchronization guard around `hostWrapper` access (or moving all access behind `startOnce`) should eliminate this race.

> [!NOTE]
>
> 🔒 Integrity filtering filtered 3 items
>
> Integrity filtering activated and filtered the following items during workflow execution.
> This happens when a tool call accesses a resource that does not meet the required integrity or secrecy level of the workflow.
>
> - issue:elastic/beats#unknown (`search_issues`: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".)
> - issue:elastic/beats#49185 (`issue_read`: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".)
> - issue:elastic/beats#49691 (`issue_read`: has lower integrity than agent requires. The agent cannot read data with integrity below "approved".)
>
>

---
[What is this?](https://ela.st/github-ai-tools) | [From workflow: Bug Hunter](https://github.com/elastic/beats/actions/runs/24187511374)

Give us feedback! React with 🚀 if perfect, 👍 if helpful, 👎 if not.
> - [x] expires on Apr 16, 2026, 11:43 AM UTC

Contributor guide

Open the contributing guide

Research direction

Start with internal/otel/sharedcomponent/sharedcomponent.go, especially the hostWrapper access at lines 105 and 108, and add or run internal/otel/sharedcomponent/race_repro_test.go. Use go test -race ./internal/otel/sharedcomponent -run TestStartConcurrentRaceRepro -count=1; done means concurrent Component.Start calls complete without race warnings or errors.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
backend, testing-qa
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
70/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.