mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-09 12:07:47 +00:00
Merge pull request #129170 from benluddy/cyclic-marshaler-cache-race
Fix data race in CBOR serializer's custom marshaler type cache.
This commit is contained in:
commit
5c207d6fb0
@ -140,7 +140,7 @@ func (cache *checkers) getCheckerInternal(rt reflect.Type, parent *path) (c chec
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
defer wg.Done()
|
||||
c = checker{
|
||||
placeholder := checker{
|
||||
safe: func() bool {
|
||||
wg.Wait()
|
||||
return c.safe()
|
||||
@ -150,7 +150,7 @@ func (cache *checkers) getCheckerInternal(rt reflect.Type, parent *path) (c chec
|
||||
return c.check(rv, depth)
|
||||
},
|
||||
}
|
||||
if actual, loaded := cache.m.LoadOrStore(rt, &c); loaded {
|
||||
if actual, loaded := cache.m.LoadOrStore(rt, &placeholder); loaded {
|
||||
// Someone else stored an entry for this type, use it.
|
||||
return *actual.(*checker)
|
||||
}
|
||||
|
@ -14,15 +14,15 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package modes_test
|
||||
package modes
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer/cbor/internal/modes"
|
||||
|
||||
"github.com/fxamacker/cbor/v2"
|
||||
)
|
||||
|
||||
@ -132,7 +132,7 @@ func TestCheckUnsupportedMarshalers(t *testing.T) {
|
||||
SafeCyclicTypeA{},
|
||||
SafeCyclicTypeB{},
|
||||
} {
|
||||
if err := modes.RejectCustomMarshalers(v); err != nil {
|
||||
if err := RejectCustomMarshalers(v); err != nil {
|
||||
t.Errorf("%#v: unexpected non-nil error: %v", v, err)
|
||||
}
|
||||
}
|
||||
@ -161,9 +161,38 @@ func TestCheckUnsupportedMarshalers(t *testing.T) {
|
||||
UnsafeCyclicTypeA{Bs: []UnsafeCyclicTypeB{{}}},
|
||||
UnsafeCyclicTypeB{},
|
||||
} {
|
||||
if err := modes.RejectCustomMarshalers(v); err == nil {
|
||||
if err := RejectCustomMarshalers(v); err == nil {
|
||||
t.Errorf("%#v: unexpected nil error", v)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// With -test.race, retrieves a custom marshaler checker for a cyclic type concurrently from many
|
||||
// goroutines to root out data races in checker lazy initialization.
|
||||
func TestLazyCheckerInitializationDataRace(t *testing.T) {
|
||||
cache := checkers{
|
||||
cborInterface: reflect.TypeFor[cbor.Marshaler](),
|
||||
nonCBORInterfaces: []reflect.Type{
|
||||
reflect.TypeFor[json.Marshaler](),
|
||||
reflect.TypeFor[encoding.TextMarshaler](),
|
||||
},
|
||||
}
|
||||
|
||||
rt := reflect.TypeFor[SafeCyclicTypeA]()
|
||||
|
||||
begin := make(chan struct{})
|
||||
|
||||
var wg sync.WaitGroup
|
||||
for range 32 {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
<-begin
|
||||
cache.getChecker(rt)
|
||||
}()
|
||||
}
|
||||
|
||||
close(begin)
|
||||
wg.Wait()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user