I've stumbled upon this in a service where schema is not parsed globally in a init func, but passed as a dependency to given resolver. Placing t.Parallel() before schema parsing causes data races found by the race detector. Placing it after the parsing solves the issue. Decided to try and reproduce it with the starwars example.
Example tests over github.com/graph-gophers/graphql-go/example/starwars with t.Parallel():
package starwars_test
import (
"testing"
graphql "github.com/graph-gophers/graphql-go"
"github.com/graph-gophers/graphql-go/example/starwars"
)
func TestParse1(t *testing.T) {
t.Parallel()
graphql.ParseSchema(starwars.Schema, &starwars.Resolver{})
}
func TestParse2(t *testing.T) {
t.Parallel()
graphql.ParseSchema(starwars.Schema, &starwars.Resolver{})
}
When executed with the race detector:
==================
WARNING: DATA RACE
Read at 0x00c4200b8928 by goroutine 6:
github.com/graph-gophers/graphql-go/internal/schema.resolveField()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:348 +0xc5
github.com/graph-gophers/graphql-go/internal/schema.resolveNamedType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:329 +0x2f5
github.com/graph-gophers/graphql-go/internal/schema.(*Schema).Parse()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:258 +0x211
github.com/graph-gophers/graphql-go.ParseSchema()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/graphql.go:37 +0x23a
github.com/graph-gophers/graphql-go/example/starwars_test.TestParse1()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/example/starwars/starwars_test.go:12 +0xa9
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
Previous write at 0x00c4200b8928 by goroutine 7:
github.com/graph-gophers/graphql-go/internal/schema.resolveField()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:352 +0x131
github.com/graph-gophers/graphql-go/internal/schema.resolveNamedType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:329 +0x2f5
github.com/graph-gophers/graphql-go/internal/schema.(*Schema).Parse()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:258 +0x211
github.com/graph-gophers/graphql-go.ParseSchema()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/graphql.go:37 +0x23a
github.com/graph-gophers/graphql-go/example/starwars_test.TestParse2()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/example/starwars/starwars_test.go:17 +0xa9
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
Goroutine 6 (running) created at:
testing.(*T).Run()
/usr/lib/go/src/testing/testing.go:824 +0x564
testing.runTests.func1()
/usr/lib/go/src/testing/testing.go:1063 +0xa4
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
testing.runTests()
/usr/lib/go/src/testing/testing.go:1061 +0x4e1
testing.(*M).Run()
/usr/lib/go/src/testing/testing.go:978 +0x2cd
main.main()
_testmain.go:46 +0x22a
Goroutine 7 (running) created at:
testing.(*T).Run()
/usr/lib/go/src/testing/testing.go:824 +0x564
testing.runTests.func1()
/usr/lib/go/src/testing/testing.go:1063 +0xa4
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
testing.runTests()
/usr/lib/go/src/testing/testing.go:1061 +0x4e1
testing.(*M).Run()
/usr/lib/go/src/testing/testing.go:978 +0x2cd
main.main()
_testmain.go:46 +0x22a
==================
==================
WARNING: DATA RACE
Read at 0x00c420197660 by goroutine 6:
github.com/graph-gophers/graphql-go/internal/common.ResolveType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/common/types.go:63 +0x129
github.com/graph-gophers/graphql-go/internal/schema.resolveField()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:348 +0xf0
github.com/graph-gophers/graphql-go/internal/schema.resolveNamedType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:329 +0x2f5
github.com/graph-gophers/graphql-go/internal/schema.(*Schema).Parse()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:258 +0x211
github.com/graph-gophers/graphql-go.ParseSchema()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/graphql.go:37 +0x23a
github.com/graph-gophers/graphql-go/example/starwars_test.TestParse1()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/example/starwars/starwars_test.go:12 +0xa9
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
Previous write at 0x00c420197660 by goroutine 7:
github.com/graph-gophers/graphql-go/internal/common.ResolveType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/common/types.go:67 +0x198
github.com/graph-gophers/graphql-go/internal/schema.resolveField()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:348 +0xf0
github.com/graph-gophers/graphql-go/internal/schema.resolveNamedType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:329 +0x2f5
github.com/graph-gophers/graphql-go/internal/schema.(*Schema).Parse()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:258 +0x211
github.com/graph-gophers/graphql-go.ParseSchema()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/graphql.go:37 +0x23a
github.com/graph-gophers/graphql-go/example/starwars_test.TestParse2()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/example/starwars/starwars_test.go:17 +0xa9
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
Goroutine 6 (running) created at:
testing.(*T).Run()
/usr/lib/go/src/testing/testing.go:824 +0x564
testing.runTests.func1()
/usr/lib/go/src/testing/testing.go:1063 +0xa4
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
testing.runTests()
/usr/lib/go/src/testing/testing.go:1061 +0x4e1
testing.(*M).Run()
/usr/lib/go/src/testing/testing.go:978 +0x2cd
main.main()
_testmain.go:46 +0x22a
Goroutine 7 (running) created at:
testing.(*T).Run()
/usr/lib/go/src/testing/testing.go:824 +0x564
testing.runTests.func1()
/usr/lib/go/src/testing/testing.go:1063 +0xa4
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
testing.runTests()
/usr/lib/go/src/testing/testing.go:1061 +0x4e1
testing.(*M).Run()
/usr/lib/go/src/testing/testing.go:978 +0x2cd
main.main()
_testmain.go:46 +0x22a
==================
==================
WARNING: DATA RACE
Read at 0x00c4201976b0 by goroutine 6:
github.com/graph-gophers/graphql-go/internal/common.ResolveType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/common/types.go:57 +0x4f1
github.com/graph-gophers/graphql-go/internal/schema.resolveField()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:348 +0xf0
github.com/graph-gophers/graphql-go/internal/schema.resolveNamedType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:329 +0x2f5
github.com/graph-gophers/graphql-go/internal/schema.(*Schema).Parse()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:258 +0x211
github.com/graph-gophers/graphql-go.ParseSchema()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/graphql.go:37 +0x23a
github.com/graph-gophers/graphql-go/example/starwars_test.TestParse1()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/example/starwars/starwars_test.go:12 +0xa9
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
Previous write at 0x00c4201976b0 by goroutine 7:
github.com/graph-gophers/graphql-go/internal/common.ResolveType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/common/types.go:61 +0x560
github.com/graph-gophers/graphql-go/internal/schema.resolveField()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:348 +0xf0
github.com/graph-gophers/graphql-go/internal/schema.resolveNamedType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:329 +0x2f5
github.com/graph-gophers/graphql-go/internal/schema.(*Schema).Parse()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:258 +0x211
github.com/graph-gophers/graphql-go.ParseSchema()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/graphql.go:37 +0x23a
github.com/graph-gophers/graphql-go/example/starwars_test.TestParse2()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/example/starwars/starwars_test.go:17 +0xa9
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
Goroutine 6 (running) created at:
testing.(*T).Run()
/usr/lib/go/src/testing/testing.go:824 +0x564
testing.runTests.func1()
/usr/lib/go/src/testing/testing.go:1063 +0xa4
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
testing.runTests()
/usr/lib/go/src/testing/testing.go:1061 +0x4e1
testing.(*M).Run()
/usr/lib/go/src/testing/testing.go:978 +0x2cd
main.main()
_testmain.go:46 +0x22a
Goroutine 7 (running) created at:
testing.(*T).Run()
/usr/lib/go/src/testing/testing.go:824 +0x564
testing.runTests.func1()
/usr/lib/go/src/testing/testing.go:1063 +0xa4
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
testing.runTests()
/usr/lib/go/src/testing/testing.go:1061 +0x4e1
testing.(*M).Run()
/usr/lib/go/src/testing/testing.go:978 +0x2cd
main.main()
_testmain.go:46 +0x22a
==================
==================
WARNING: DATA RACE
Read at 0x00c4201976a0 by goroutine 6:
github.com/graph-gophers/graphql-go/internal/common.ResolveType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/common/types.go:63 +0x129
github.com/graph-gophers/graphql-go/internal/common.ResolveType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/common/types.go:57 +0x518
github.com/graph-gophers/graphql-go/internal/schema.resolveField()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:348 +0xf0
github.com/graph-gophers/graphql-go/internal/schema.resolveNamedType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:329 +0x2f5
github.com/graph-gophers/graphql-go/internal/schema.(*Schema).Parse()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:258 +0x211
github.com/graph-gophers/graphql-go.ParseSchema()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/graphql.go:37 +0x23a
github.com/graph-gophers/graphql-go/example/starwars_test.TestParse1()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/example/starwars/starwars_test.go:12 +0xa9
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
Previous write at 0x00c4201976a0 by goroutine 7:
github.com/graph-gophers/graphql-go/internal/common.ResolveType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/common/types.go:67 +0x198
github.com/graph-gophers/graphql-go/internal/common.ResolveType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/common/types.go:57 +0x518
github.com/graph-gophers/graphql-go/internal/schema.resolveField()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:348 +0xf0
github.com/graph-gophers/graphql-go/internal/schema.resolveNamedType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:329 +0x2f5
github.com/graph-gophers/graphql-go/internal/schema.(*Schema).Parse()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:258 +0x211
github.com/graph-gophers/graphql-go.ParseSchema()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/graphql.go:37 +0x23a
github.com/graph-gophers/graphql-go/example/starwars_test.TestParse2()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/example/starwars/starwars_test.go:17 +0xa9
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
Goroutine 6 (running) created at:
testing.(*T).Run()
/usr/lib/go/src/testing/testing.go:824 +0x564
testing.runTests.func1()
/usr/lib/go/src/testing/testing.go:1063 +0xa4
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
testing.runTests()
/usr/lib/go/src/testing/testing.go:1061 +0x4e1
testing.(*M).Run()
/usr/lib/go/src/testing/testing.go:978 +0x2cd
main.main()
_testmain.go:46 +0x22a
Goroutine 7 (running) created at:
testing.(*T).Run()
/usr/lib/go/src/testing/testing.go:824 +0x564
testing.runTests.func1()
/usr/lib/go/src/testing/testing.go:1063 +0xa4
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
testing.runTests()
/usr/lib/go/src/testing/testing.go:1061 +0x4e1
testing.(*M).Run()
/usr/lib/go/src/testing/testing.go:978 +0x2cd
main.main()
_testmain.go:46 +0x22a
==================
==================
WARNING: DATA RACE
Read at 0x00c4200d04f0 by goroutine 6:
github.com/graph-gophers/graphql-go/internal/schema.resolveInputObject()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:382 +0xfc
github.com/graph-gophers/graphql-go/internal/schema.resolveField()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:356 +0x22b
github.com/graph-gophers/graphql-go/internal/schema.resolveNamedType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:329 +0x2f5
github.com/graph-gophers/graphql-go/internal/schema.(*Schema).Parse()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:258 +0x211
github.com/graph-gophers/graphql-go.ParseSchema()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/graphql.go:37 +0x23a
github.com/graph-gophers/graphql-go/example/starwars_test.TestParse1()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/example/starwars/starwars_test.go:12 +0xa9
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
Previous write at 0x00c4200d04f0 by goroutine 7:
github.com/graph-gophers/graphql-go/internal/schema.resolveInputObject()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:386 +0x15b
github.com/graph-gophers/graphql-go/internal/schema.resolveField()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:356 +0x22b
github.com/graph-gophers/graphql-go/internal/schema.resolveNamedType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:329 +0x2f5
github.com/graph-gophers/graphql-go/internal/schema.(*Schema).Parse()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:258 +0x211
github.com/graph-gophers/graphql-go.ParseSchema()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/graphql.go:37 +0x23a
github.com/graph-gophers/graphql-go/example/starwars_test.TestParse2()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/example/starwars/starwars_test.go:17 +0xa9
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
Goroutine 6 (running) created at:
testing.(*T).Run()
/usr/lib/go/src/testing/testing.go:824 +0x564
testing.runTests.func1()
/usr/lib/go/src/testing/testing.go:1063 +0xa4
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
testing.runTests()
/usr/lib/go/src/testing/testing.go:1061 +0x4e1
testing.(*M).Run()
/usr/lib/go/src/testing/testing.go:978 +0x2cd
main.main()
_testmain.go:46 +0x22a
Goroutine 7 (running) created at:
testing.(*T).Run()
/usr/lib/go/src/testing/testing.go:824 +0x564
testing.runTests.func1()
/usr/lib/go/src/testing/testing.go:1063 +0xa4
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
testing.runTests()
/usr/lib/go/src/testing/testing.go:1061 +0x4e1
testing.(*M).Run()
/usr/lib/go/src/testing/testing.go:978 +0x2cd
main.main()
_testmain.go:46 +0x22a
==================
==================
WARNING: DATA RACE
Read at 0x00c4200b8c28 by goroutine 6:
github.com/graph-gophers/graphql-go/internal/schema.resolveField()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:348 +0xc5
github.com/graph-gophers/graphql-go/internal/schema.resolveNamedType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:329 +0x2f5
github.com/graph-gophers/graphql-go/internal/schema.(*Schema).Parse()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:258 +0x211
github.com/graph-gophers/graphql-go.ParseSchema()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/graphql.go:37 +0x23a
github.com/graph-gophers/graphql-go/example/starwars_test.TestParse1()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/example/starwars/starwars_test.go:12 +0xa9
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
Previous write at 0x00c4200b8c28 by goroutine 7:
[failed to restore the stack]
Goroutine 6 (running) created at:
testing.(*T).Run()
/usr/lib/go/src/testing/testing.go:824 +0x564
testing.runTests.func1()
/usr/lib/go/src/testing/testing.go:1063 +0xa4
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
testing.runTests()
/usr/lib/go/src/testing/testing.go:1061 +0x4e1
testing.(*M).Run()
/usr/lib/go/src/testing/testing.go:978 +0x2cd
main.main()
_testmain.go:46 +0x22a
Goroutine 7 (running) created at:
testing.(*T).Run()
/usr/lib/go/src/testing/testing.go:824 +0x564
testing.runTests.func1()
/usr/lib/go/src/testing/testing.go:1063 +0xa4
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
testing.runTests()
/usr/lib/go/src/testing/testing.go:1061 +0x4e1
testing.(*M).Run()
/usr/lib/go/src/testing/testing.go:978 +0x2cd
main.main()
_testmain.go:46 +0x22a
==================
==================
WARNING: DATA RACE
Read at 0x00c4201970a0 by goroutine 6:
github.com/graph-gophers/graphql-go/internal/common.ResolveType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/common/types.go:63 +0x129
github.com/graph-gophers/graphql-go/internal/schema.resolveField()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:348 +0xf0
github.com/graph-gophers/graphql-go/internal/schema.resolveNamedType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:329 +0x2f5
github.com/graph-gophers/graphql-go/internal/schema.(*Schema).Parse()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:258 +0x211
github.com/graph-gophers/graphql-go.ParseSchema()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/graphql.go:37 +0x23a
github.com/graph-gophers/graphql-go/example/starwars_test.TestParse1()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/example/starwars/starwars_test.go:12 +0xa9
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
Previous write at 0x00c4201970a0 by goroutine 7:
[failed to restore the stack]
Goroutine 6 (running) created at:
testing.(*T).Run()
/usr/lib/go/src/testing/testing.go:824 +0x564
testing.runTests.func1()
/usr/lib/go/src/testing/testing.go:1063 +0xa4
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
testing.runTests()
/usr/lib/go/src/testing/testing.go:1061 +0x4e1
testing.(*M).Run()
/usr/lib/go/src/testing/testing.go:978 +0x2cd
main.main()
_testmain.go:46 +0x22a
Goroutine 7 (running) created at:
testing.(*T).Run()
/usr/lib/go/src/testing/testing.go:824 +0x564
testing.runTests.func1()
/usr/lib/go/src/testing/testing.go:1063 +0xa4
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
testing.runTests()
/usr/lib/go/src/testing/testing.go:1061 +0x4e1
testing.(*M).Run()
/usr/lib/go/src/testing/testing.go:978 +0x2cd
main.main()
_testmain.go:46 +0x22a
==================
==================
WARNING: DATA RACE
Read at 0x00c4201970e0 by goroutine 6:
github.com/graph-gophers/graphql-go/internal/common.ResolveType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/common/types.go:57 +0x4f1
github.com/graph-gophers/graphql-go/internal/common.ResolveType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/common/types.go:63 +0x150
github.com/graph-gophers/graphql-go/internal/schema.resolveField()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:348 +0xf0
github.com/graph-gophers/graphql-go/internal/schema.resolveNamedType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:329 +0x2f5
github.com/graph-gophers/graphql-go/internal/schema.(*Schema).Parse()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:258 +0x211
github.com/graph-gophers/graphql-go.ParseSchema()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/graphql.go:37 +0x23a
github.com/graph-gophers/graphql-go/example/starwars_test.TestParse1()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/example/starwars/starwars_test.go:12 +0xa9
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
Previous write at 0x00c4201970e0 by goroutine 7:
[failed to restore the stack]
Goroutine 6 (running) created at:
testing.(*T).Run()
/usr/lib/go/src/testing/testing.go:824 +0x564
testing.runTests.func1()
/usr/lib/go/src/testing/testing.go:1063 +0xa4
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
testing.runTests()
/usr/lib/go/src/testing/testing.go:1061 +0x4e1
testing.(*M).Run()
/usr/lib/go/src/testing/testing.go:978 +0x2cd
main.main()
_testmain.go:46 +0x22a
Goroutine 7 (running) created at:
testing.(*T).Run()
/usr/lib/go/src/testing/testing.go:824 +0x564
testing.runTests.func1()
/usr/lib/go/src/testing/testing.go:1063 +0xa4
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
testing.runTests()
/usr/lib/go/src/testing/testing.go:1061 +0x4e1
testing.(*M).Run()
/usr/lib/go/src/testing/testing.go:978 +0x2cd
main.main()
_testmain.go:46 +0x22a
==================
==================
WARNING: DATA RACE
Read at 0x00c4201970d0 by goroutine 6:
github.com/graph-gophers/graphql-go/internal/common.ResolveType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/common/types.go:63 +0x129
github.com/graph-gophers/graphql-go/internal/common.ResolveType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/common/types.go:57 +0x518
github.com/graph-gophers/graphql-go/internal/common.ResolveType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/common/types.go:63 +0x150
github.com/graph-gophers/graphql-go/internal/schema.resolveField()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:348 +0xf0
github.com/graph-gophers/graphql-go/internal/schema.resolveNamedType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:329 +0x2f5
github.com/graph-gophers/graphql-go/internal/schema.(*Schema).Parse()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:258 +0x211
github.com/graph-gophers/graphql-go.ParseSchema()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/graphql.go:37 +0x23a
github.com/graph-gophers/graphql-go/example/starwars_test.TestParse1()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/example/starwars/starwars_test.go:12 +0xa9
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
Previous write at 0x00c4201970d0 by goroutine 7:
[failed to restore the stack]
Goroutine 6 (running) created at:
testing.(*T).Run()
/usr/lib/go/src/testing/testing.go:824 +0x564
testing.runTests.func1()
/usr/lib/go/src/testing/testing.go:1063 +0xa4
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
testing.runTests()
/usr/lib/go/src/testing/testing.go:1061 +0x4e1
testing.(*M).Run()
/usr/lib/go/src/testing/testing.go:978 +0x2cd
main.main()
_testmain.go:46 +0x22a
Goroutine 7 (running) created at:
testing.(*T).Run()
/usr/lib/go/src/testing/testing.go:824 +0x564
testing.runTests.func1()
/usr/lib/go/src/testing/testing.go:1063 +0xa4
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
testing.runTests()
/usr/lib/go/src/testing/testing.go:1061 +0x4e1
testing.(*M).Run()
/usr/lib/go/src/testing/testing.go:978 +0x2cd
main.main()
_testmain.go:46 +0x22a
==================
==================
WARNING: DATA RACE
Read at 0x00c4200d0100 by goroutine 6:
github.com/graph-gophers/graphql-go/internal/schema.(*Schema).Parse()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:264 +0x3b5
github.com/graph-gophers/graphql-go.ParseSchema()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/graphql.go:37 +0x23a
github.com/graph-gophers/graphql-go/example/starwars_test.TestParse1()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/example/starwars/starwars_test.go:12 +0xa9
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
Previous write at 0x00c4200d0100 by goroutine 7:
[failed to restore the stack]
Goroutine 6 (running) created at:
testing.(*T).Run()
/usr/lib/go/src/testing/testing.go:824 +0x564
testing.runTests.func1()
/usr/lib/go/src/testing/testing.go:1063 +0xa4
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
testing.runTests()
/usr/lib/go/src/testing/testing.go:1061 +0x4e1
testing.(*M).Run()
/usr/lib/go/src/testing/testing.go:978 +0x2cd
main.main()
_testmain.go:46 +0x22a
Goroutine 7 (running) created at:
testing.(*T).Run()
/usr/lib/go/src/testing/testing.go:824 +0x564
testing.runTests.func1()
/usr/lib/go/src/testing/testing.go:1063 +0xa4
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
testing.runTests()
/usr/lib/go/src/testing/testing.go:1061 +0x4e1
testing.(*M).Run()
/usr/lib/go/src/testing/testing.go:978 +0x2cd
main.main()
_testmain.go:46 +0x22a
==================
==================
WARNING: DATA RACE
Read at 0x00c420197b90 by goroutine 6:
github.com/graph-gophers/graphql-go/internal/common.ResolveType()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/common/types.go:63 +0x129
github.com/graph-gophers/graphql-go/internal/schema.(*Schema).Parse()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/internal/schema/schema.go:264 +0x3e0
github.com/graph-gophers/graphql-go.ParseSchema()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/graphql.go:37 +0x23a
github.com/graph-gophers/graphql-go/example/starwars_test.TestParse1()
/home/kiril/go/src/github.com/graph-gophers/graphql-go/example/starwars/starwars_test.go:12 +0xa9
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
Previous write at 0x00c420197b90 by goroutine 7:
[failed to restore the stack]
Goroutine 6 (running) created at:
testing.(*T).Run()
/usr/lib/go/src/testing/testing.go:824 +0x564
testing.runTests.func1()
/usr/lib/go/src/testing/testing.go:1063 +0xa4
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
testing.runTests()
/usr/lib/go/src/testing/testing.go:1061 +0x4e1
testing.(*M).Run()
/usr/lib/go/src/testing/testing.go:978 +0x2cd
main.main()
_testmain.go:46 +0x22a
Goroutine 7 (running) created at:
testing.(*T).Run()
/usr/lib/go/src/testing/testing.go:824 +0x564
testing.runTests.func1()
/usr/lib/go/src/testing/testing.go:1063 +0xa4
testing.tRunner()
/usr/lib/go/src/testing/testing.go:777 +0x16d
testing.runTests()
/usr/lib/go/src/testing/testing.go:1061 +0x4e1
testing.(*M).Run()
/usr/lib/go/src/testing/testing.go:978 +0x2cd
main.main()
_testmain.go:46 +0x22a
==================
--- FAIL: TestParse2 (0.01s)
testing.go:730: race detected during execution of test
--- FAIL: TestParse1 (0.01s)
testing.go:730: race detected during execution of test
FAIL
FAIL github.com/graph-gophers/graphql-go/example/starwars 0.020s
Thanks for the report, will make sure to look into it.
I don't believe that ParseSchema was intended to be called in parallel (or even more than once per application start), for what it's worth. Can you tell me more about your usecase?
I need to run it several times only in tests. Having one global (Must)?Parse call in init func wouldn't suffice, because depending on what it's being tested the resolver's dependencies need to be configured first (e.g. use a real database/email provider/payment gateway/key store/... or a mock).
Obviously this leads to redundant schema parsing, because there doesn't seem to be a way to parse once the raw GraphQL schema string/file in init (because I can't think of proper case where dynamically changing the GraphQL schema makes sense) and then pass a configured resolver to that semi-parsed schema value.
Currently I work around this by calling t.Parallel() after schema parsing.
Thanks for the additional details. I'll look into the issue 馃憤
I'm about to write tests that will trigger this behaviour and I think I can add my own global lock to work around the race for now, but I tried debugging it and I'll just post what I found out so far in case that helps.
Re-running the tests with export GORACE=history_size=7 reveals the source of the write:
Previous write at 0x00c42017db20 by goroutine 7:
<redacted>/github.com/graph-gophers/graphql-go/internal/common.ResolveType()
<redacted>/github.com/graph-gophers/graphql-go/internal/common/types.go:67 +0x19e
<redacted>/github.com/graph-gophers/graphql-go/internal/schema.(*Schema).Parse()
<redacted>/github.com/graph-gophers/graphql-go/internal/schema/schema.go:264 +0x7ec
<redacted>/github.com/graph-gophers/graphql-go.ParseSchema()
<redacted>/github.com/graph-gophers/graphql-go/graphql.go:36 +0x21b
command-line-arguments_test.TestParse2()
<redacted>/test/graphql_test.go:17 +0xb3
testing.tRunner()
/usr/local/go/src/testing/testing.go:746 +0x16c
I can't make sense of this race so far. Allegedly,
return &NonNull{OfType: ofType}, nil
(the write) is racing with
ofType, err := ResolveType(t.OfType, resolver)
(the read) on the previous line.
(edit: I thought I found something that fixes the race but I didn't... still trying stuff now...)
By moving stuff around a bit, I found that t.OfType is racing with NonNull{OfType: ofType} but that makes no sense.
Looking at this problem again, I the root cause of the race is the sharing of Types and Directives between new schemas and the Meta schema. I suspect that copying Meta.Types and Meta.Directives in schema.New will resolve the race. It's not easy to copy structs passed through interfaces in go, so I'll try this another day, but I'd be happy if someone has an idea for how to make those copies work or for a different solution.
Most helpful comment
Looking at this problem again, I the root cause of the race is the sharing of Types and Directives between new schemas and the Meta schema. I suspect that copying Meta.Types and Meta.Directives in schema.New will resolve the race. It's not easy to copy structs passed through interfaces in go, so I'll try this another day, but I'd be happy if someone has an idea for how to make those copies work or for a different solution.