Commit e855fcc3 authored by Rob Pike's avatar Rob Pike

encoding/gob: fix data race in Register

Fixes #4214.

R=golang-dev, dsymonds, bradfitz
CC=golang-dev
https://golang.org/cl/6637047
parent e9f0fc88
......@@ -717,7 +717,9 @@ func (dec *Decoder) decodeInterface(ityp reflect.Type, state *decoderState, p ui
errorf("name too long (%d bytes): %.20q...", len(name), name)
}
// The concrete type must be registered.
registerLock.RLock()
typ, ok := nameToConcreteType[name]
registerLock.RUnlock()
if !ok {
errorf("name not registered for interface: %q", name)
}
......
......@@ -441,7 +441,9 @@ func (enc *Encoder) encodeInterface(b *bytes.Buffer, iv reflect.Value) {
}
ut := userType(iv.Elem().Type())
registerLock.RLock()
name, ok := concreteTypeToName[ut.base]
registerLock.RUnlock()
if !ok {
errorf("type not registered for interface: %s", ut.base)
}
......
......@@ -712,6 +712,7 @@ type GobDecoder interface {
}
var (
registerLock sync.RWMutex
nameToConcreteType = make(map[string]reflect.Type)
concreteTypeToName = make(map[reflect.Type]string)
)
......@@ -723,6 +724,8 @@ func RegisterName(name string, value interface{}) {
// reserved for nil
panic("attempt to register empty name")
}
registerLock.Lock()
defer registerLock.Unlock()
ut := userType(reflect.TypeOf(value))
// Check for incompatible duplicates. The name must refer to the
// same user type, and vice versa.
......
......@@ -177,7 +177,10 @@ func TestRegistrationNaming(t *testing.T) {
Register(tc.t)
tct := reflect.TypeOf(tc.t)
if ct := nameToConcreteType[tc.name]; ct != tct {
registerLock.RLock()
ct := nameToConcreteType[tc.name]
registerLock.RUnlock()
if ct != tct {
t.Errorf("nameToConcreteType[%q] = %v, want %v", tc.name, ct, tct)
}
// concreteTypeToName is keyed off the base type.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment