-
Notifications
You must be signed in to change notification settings - Fork 144
Open
Description
There may be a concurrency issue where the goroutine writes to newProject.Services while the for loop reads it:
eg.Go(func() error { // line 799: collector goroutine starts
s := Services{}
for expect > 0 { // line 801: if expect==0, skip loop entirely
// ...
s[r.name] = r.service
expect--
}
newProject.Services = s // line 811: WRITE to newProject.Services
return nil
})
for n, s := range newProject.Services { // line 814: READ newProject.Services
// ... spawn workers
}
Here is the -race output specifying a read at project.go:814 and a write at project.go:811:
WARNING: DATA RACE
Write at 0x00c0008102a0 by goroutine 34:
github.com/compose-spec/compose-go/v2/types.(*Project).WithServicesTransform.func1()
/Users/user/go/pkg/mod/github.com/compose-spec/compose-go/v2@v2.9.0/types/project.go:811 +0x230
golang.org/x/sync/errgroup.(*Group).Go.func1()
/Users/user/go/pkg/mod/golang.org/x/sync@v0.19.0/errgroup/errgroup.go:93 +0x70
Previous read at 0x00c0008102a0 by goroutine 33:
github.com/compose-spec/compose-go/v2/types.(*Project).WithServicesTransform()
/Users/user/go/pkg/mod/github.com/compose-spec/compose-go/v2@v2.9.0/types/project.go:814 +0x2d4
github.com/docker/compose/v2/pkg/compose.(*composeService).getProjectWithResources()
/Users/user/go/pkg/mod/github.com/docker/compose/v2@v2.40.2/pkg/compose/down.go:386 +0xe4
github.com/docker/compose/v2/pkg/compose.(*composeService).down()
/Users/user/go/pkg/mod/github.com/docker/compose/v2@v2.40.2/pkg/compose/down.go:61 +0x128
github.com/docker/compose/v2/pkg/compose.(*composeService).down()
/Users/user/go/pkg/mod/github.com/docker/compose/v2@v2.40.2/pkg/compose/down.go:54 +0xec
github.com/docker/compose/v2/pkg/compose.(*composeService).Down.func1()
/Users/user/go/pkg/mod/github.com/docker/compose/v2@v2.40.2/pkg/compose/down.go:42 +0xa4
github.com/docker/compose/v2/pkg/progress.Run.func1()
/Users/user/go/pkg/mod/github.com/docker/compose/v2@v2.40.2/pkg/progress/writer.go:63 +0x44
github.com/docker/compose/v2/pkg/progress.RunWithStatus.func2()
/Users/user/go/pkg/mod/github.com/docker/compose/v2@v2.40.2/pkg/progress/writer.go:110 +0xa4
golang.org/x/sync/errgroup.(*Group).Go.func1()
/Users/user/go/pkg/mod/golang.org/x/sync@v0.19.0/errgroup/errgroup.go:93 +0x70
Goroutine 34 (running) created at:
golang.org/x/sync/errgroup.(*Group).Go()
/Users/user/go/pkg/mod/golang.org/x/sync@v0.19.0/errgroup/errgroup.go:78 +0x104
github.com/compose-spec/compose-go/v2/types.(*Project).WithServicesTransform()
/Users/user/go/pkg/mod/github.com/compose-spec/compose-go/v2@v2.9.0/types/project.go:799 +0x2c4
github.com/docker/compose/v2/pkg/compose.(*composeService).getProjectWithResources()
/Users/user/go/pkg/mod/github.com/docker/compose/v2@v2.40.2/pkg/compose/down.go:386 +0xe4
github.com/docker/compose/v2/pkg/compose.(*composeService).down()
/Users/user/go/pkg/mod/github.com/docker/compose/v2@v2.40.2/pkg/compose/down.go:61 +0x128
github.com/docker/compose/v2/pkg/compose.(*composeService).down()
/Users/user/go/pkg/mod/github.com/docker/compose/v2@v2.40.2/pkg/compose/down.go:54 +0xec
github.com/docker/compose/v2/pkg/compose.(*composeService).Down.func1()
/Users/user/go/pkg/mod/github.com/docker/compose/v2@v2.40.2/pkg/compose/down.go:42 +0xa4
github.com/docker/compose/v2/pkg/progress.Run.func1()
/Users/user/go/pkg/mod/github.com/docker/compose/v2@v2.40.2/pkg/progress/writer.go:63 +0x44
github.com/docker/compose/v2/pkg/progress.RunWithStatus.func2()
/Users/user/go/pkg/mod/github.com/docker/compose/v2@v2.40.2/pkg/progress/writer.go:110 +0xa4
golang.org/x/sync/errgroup.(*Group).Go.func1()
/Users/user/go/pkg/mod/golang.org/x/sync@v0.19.0/errgroup/errgroup.go:93 +0x70
Goroutine 33 (running) created at:
golang.org/x/sync/errgroup.(*Group).Go()
/Users/user/go/pkg/mod/golang.org/x/sync@v0.19.0/errgroup/errgroup.go:78 +0x104
github.com/docker/compose/v2/pkg/progress.RunWithStatus()
/Users/user/go/pkg/mod/github.com/docker/compose/v2@v2.40.2/pkg/progress/writer.go:108 +0x2f8
github.com/docker/compose/v2/pkg/progress.Run()
/Users/user/go/pkg/mod/github.com/docker/compose/v2@v2.40.2/pkg/progress/writer.go:62 +0xa4
github.com/docker/compose/v2/pkg/compose.(*composeService).Down()
/Users/user/go/pkg/mod/github.com/docker/compose/v2@v2.40.2/pkg/compose/down.go:41 +0x150
github.com/testcontainers/testcontainers-go/modules/compose.(*DockerCompose).Down()
/Users/user/go/pkg/mod/github.com/testcontainers/testcontainers-go/modules/compose@v0.40.0/compose_api.go:271 +0x24c
bitbucket.org/contoso/my-code-repo/e2e/infra.New()
/Users/user/Developer/contoso.com/my-code-repo/e2e/infra/testcontainers.go:111 +0x4c0
github.com/testcontainers/testcontainers-go/modules/compose.NewDockerCompose()
/Users/user/go/pkg/mod/github.com/testcontainers/testcontainers-go/modules/compose@v0.40.0/compose.go:127 +0x188
bitbucket.org/contoso/my-code-repo/e2e/infra.New()
/Users/user/Developer/contoso.com/my-code-repo/e2e/infra/testcontainers.go:83 +0x140
bitbucket.org/contoso/my-code-repo/e2e.TestMain()
/Users/user/Developer/contoso.com/my-code-repo/e2e/main_test.go:25 +0xb4
main.main()
_testmain.go:82 +0x104
==================
This patch fixes the issue locally:
--- a/vendor/github.com/compose-spec/compose-go/v2/types/project.go
+++ b/vendor/github.com/compose-spec/compose-go/v2/types/project.go
@@ -795,6 +795,10 @@
resultCh := make(chan result, expect)
newProject := p.deepCopy()
+ // Capture services before spawning the collector goroutine to avoid
+ // a data race between the collector writing newProject.Services and
+ // the range reading it. See https://github.com/compose-spec/compose-go/issues/852
+ services := newProject.Services
eg, ctx := errgroup.WithContext(context.Background())
eg.Go(func() error {
s := Services{}
@@ -811,7 +815,7 @@
newProject.Services = s
return nil
})
- for n, s := range newProject.Services {
+ for n, s := range services {
name := n
service := s
eg.Go(func() error {
Versions: compose-spec/compose-go/v2 v2.9.0, docker/compose/v2 v2.40.2, testcontainers-go v0.40.0
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels