Closed
Description
(discovered while debugging golang/protobuf#838)
Consider the following main.go
:
package main
import (
"sync"
// github.com/golang/[email protected]
"github.com/golang/protobuf/jsonpb"
"github.com/golang/protobuf/proto"
descriptorpb "github.com/golang/protobuf/protoc-gen-go/descriptor"
)
func main() {
obj := &descriptorpb.FileDescriptorProto{
Options: &descriptorpb.FileOptions{
GoPackage: proto.String("path/to/my/package"),
},
}
wg := &sync.WaitGroup{}
defer wg.Wait()
wg.Add(1)
go func() {
defer wg.Done()
proto.Marshal(obj)
}()
wg.Add(1)
go func() {
defer wg.Done()
(&jsonpb.Marshaler{}).MarshalToString(obj)
}()
}
When running go run -race main.go
, I see (-go1.12 +go1.11):
==================
WARNING: DATA RACE
Read at 0x000000000000 by goroutine 7:
reflect.typedmemmove()
/usr/local/go/src/runtime/mbarrier.go:177
reflect.packEface()
/usr/local/go/src/reflect/value.go:119
reflect.valueInterface()
- /usr/local/go/src/reflect/value.go:1009
+ /usr/local/go/src/reflect/value.go:978
+ reflect.Value.Interface()
+ /usr/local/go/src/reflect/value.go:948
github.com/golang/protobuf/jsonpb.(*Marshaler).marshalValue()
- /usr/local/go/src/reflect/value.go:979
+ /usr/local/protobuf-golang/jsonpb/jsonpb.go:534
github.com/golang/protobuf/jsonpb.(*Marshaler).marshalField()
/usr/local/protobuf-golang/jsonpb/jsonpb.go:488
github.com/golang/protobuf/jsonpb.(*Marshaler).marshalObject()
/usr/local/protobuf-golang/jsonpb/jsonpb.go:346
github.com/golang/protobuf/jsonpb.(*Marshaler).Marshal()
/usr/local/protobuf-golang/jsonpb/jsonpb.go:139
github.com/golang/protobuf/jsonpb.(*Marshaler).MarshalToString()
/usr/local/protobuf-golang/jsonpb/jsonpb.go:145
main.main.func2()
/Users/rawr/blah/test.go:31
Previous write at 0x000000000000 by goroutine 6:
sync/atomic.StoreInt32()
/usr/local/go/src/runtime/race_amd64.s:229
github.com/golang/protobuf/proto.(*marshalInfo).size()
/usr/local/protobuf-golang/proto/table_marshal.go:203
github.com/golang/protobuf/proto.makeMessageMarshaler.func1()
/usr/local/protobuf-golang/proto/table_marshal.go:2223
github.com/golang/protobuf/proto.(*marshalInfo).size()
/usr/local/protobuf-golang/proto/table_marshal.go:183
github.com/golang/protobuf/proto.(*InternalMessageInfo).Size()
/usr/local/protobuf-golang/proto/table_marshal.go:125
github.com/golang/protobuf/protoc-gen-go/descriptor.(*FileDescriptorProto).XXX_Size()
/usr/local/protobuf-golang/protoc-gen-go/descriptor/descriptor.pb.go:435
github.com/golang/protobuf/proto.Marshal()
/usr/local/protobuf-golang/proto/table_marshal.go:2713
main.main.func1()
/Users/rawr/blah/test.go:25
Goroutine 7 (running) created at:
main.main()
/Users/rawr/blah/test.go:29
Goroutine 6 (finished) created at:
main.main()
/Users/rawr/blah/test.go:23
==================
The interesting line is /usr/local/protobuf-golang/jsonpb/jsonpb.go:534
, which is missing in the stack trace on Go1.12, presumably because of mid-stack inlining.