[bug-hunter] Data race in internal/otel/sharedcomponent Component.Start
- 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
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