Skip to content

Commit

Permalink
cue/load: fix Instances race
Browse files Browse the repository at this point in the history
The shared `*cue.Instance` used by the filetypes logic was causing
a race when loading. Using `cue.Value` instead avoids the race because
`cue.Value` is already finalized.

Updates #1746, #2480.

Signed-off-by: Roger Peppe <rogpeppe@gmail.com>
Change-Id: I48819188f1f0bbda62909f3aea8675953e2d8fc2
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/556519
Reviewed-by: Marcel van Lohuizen <mpvl@gmail.com>
Unity-Result: CUE porcuepine <cue.porcuepine@gmail.com>
TryBot-Result: CUEcueckoo <cueckoo+gerrithub@cuelang.org>
Reviewed-by: Paul Jolly <paul@myitcv.io>
  • Loading branch information
rogpeppe committed Jul 12, 2023
1 parent b16f6ce commit c10d7cb
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 15 deletions.
21 changes: 21 additions & 0 deletions cue/load/loader_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"path/filepath"
"strconv"
"strings"
"sync"
"testing"
"text/template"
"unicode"
Expand Down Expand Up @@ -439,3 +440,23 @@ func TestOverlays(t *testing.T) {
}
}
}

func TestLoadInstancesConcurrent(t *testing.T) {
// This test is designed to fail when run with the race detector
// if there's an underlying race condition.
// See https:/cuelang.org/issue/1746
race(func() {
Instances([]string{"."}, nil)
})
}

func race(f func()) {
var wg sync.WaitGroup
for i := 0; i < 2; i++ {
wg.Add(1)
go func() {
f()
wg.Done()
}()
}
}
9 changes: 6 additions & 3 deletions encoding/gocode/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func {{if .func}}{{.complete}}{{.cueName}}{{$sig}}
var loadCode = template.Must(template.New("load").Funcs(template.FuncMap{
"normalizeHex": normalizeHex,
}).Parse(`
var {{.prefix}}Codec, {{.prefix}}Instance = func() (*gocodec.Codec, *cue.Instance) {
var {{.prefix}}Codec, {{.prefix}}Instance_, {{.prefix}}Value = func() (*gocodec.Codec, *cue.Instance, cue.Value) {
var r *cue.Runtime
r = {{if .runtime}}{{.runtime}}{{else}}&cue.Runtime{}{{end}}
instances, err := r.Unmarshal({{.prefix}}InstanceData)
Expand All @@ -88,13 +88,16 @@ var {{.prefix}}Codec, {{.prefix}}Instance = func() (*gocodec.Codec, *cue.Instanc
if len(instances) != 1 {
panic("expected encoding of exactly one instance")
}
return gocodec.New(r, nil), instances[0]
return gocodec.New(r, nil), instances[0], instances[0].Value()
}()
// Deprecated: cue.Instance is deprecated. Use {{.prefix}}Value instead.
var {{.prefix}}Instance = {{.prefix}}Instance_
// {{.prefix}}Make is called in the init phase to initialize CUE values for
// validation functions.
func {{.prefix}}Make(name string, x interface{}) cue.Value {
f, err := {{.prefix}}Instance.Value().FieldByName(name, true)
f, err := {{.prefix}}Value.FieldByName(name, true)
if err != nil {
panic(fmt.Errorf("could not find type %q in instance", name))
}
Expand Down
9 changes: 6 additions & 3 deletions encoding/gocode/testdata/pkg1/cue_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 6 additions & 3 deletions encoding/gocode/testdata/pkg2/cue_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 2 additions & 3 deletions internal/filetypes/filetypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,7 @@ func FromFile(b *build.File, mode Mode) (*FileInfo, error) {
}, nil
}

i := cuegenInstance.Value()
i, errs := update(nil, i, i, "modes", mode.String())
i, errs := update(nil, cuegenValue, cuegenValue, "modes", mode.String())
v := i.LookupDef("FileInfo")
v = v.Fill(b)

Expand Down Expand Up @@ -283,7 +282,7 @@ func toFile(i, v cue.Value, filename string) (*build.File, error) {
}

func parseType(s string, mode Mode) (inst, val cue.Value, err error) {
i := cuegenInstance.Value()
i := cuegenValue
i = i.Unify(i.Lookup("modes", mode.String()))
v := i.LookupDef("File")

Expand Down
9 changes: 6 additions & 3 deletions internal/filetypes/types.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit c10d7cb

Please sign in to comment.