]> Cypherpunks repositories - gostls13.git/commitdiff
encoding/gob: fix data race in Register
authorRob Pike <r@golang.org>
Tue, 9 Oct 2012 00:56:38 +0000 (11:56 +1100)
committerRob Pike <r@golang.org>
Tue, 9 Oct 2012 00:56:38 +0000 (11:56 +1100)
Fixes #4214.

R=golang-dev, dsymonds, bradfitz
CC=golang-dev
https://golang.org/cl/6637047

src/pkg/encoding/gob/decode.go
src/pkg/encoding/gob/encode.go
src/pkg/encoding/gob/type.go
src/pkg/encoding/gob/type_test.go

index 8690b35d71481082e0ef8d8b6aebe641e9a759cc..900c69ddb478440684bdaaab1bcab452d225c459 100644 (file)
@@ -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)
        }
index e89f68fa0810a6878f9597b28ddb782f7a8a2232..ea37a6cbd589c7898e2750b8098a0693cb76ca5b 100644 (file)
@@ -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)
        }
index a8ee2fa4a5a474697b036c5cf52def4e3d019363..ea0db4eac45276a61768d3a384fcc6f35e298568 100644 (file)
@@ -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.
index 734fbb04b4c87244894041578801fd52b1788fd5..e55fba98d5a53616ead139273963480143cc59ea 100644 (file)
@@ -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.