Fix possible concurrency problem for serializer

This commit is contained in:
Jinzhu 2023-03-10 10:48:14 +08:00
parent e9f25c73ee
commit 1643a36260
2 changed files with 12 additions and 4 deletions

View File

@ -916,6 +916,8 @@ func (field *Field) setupValuerAndSetter() {
sameElemType = field.FieldType == reflect.ValueOf(field.Serializer).Type().Elem() sameElemType = field.FieldType == reflect.ValueOf(field.Serializer).Type().Elem()
} }
serializerValue := reflect.Indirect(reflect.ValueOf(field.Serializer))
serializerType := serializerValue.Type()
field.Set = func(ctx context.Context, value reflect.Value, v interface{}) (err error) { field.Set = func(ctx context.Context, value reflect.Value, v interface{}) (err error) {
if s, ok := v.(*serializer); ok { if s, ok := v.(*serializer); ok {
if s.fieldValue != nil { if s.fieldValue != nil {
@ -923,11 +925,12 @@ func (field *Field) setupValuerAndSetter() {
} else if err = s.Serializer.Scan(ctx, field, value, s.value); err == nil { } else if err = s.Serializer.Scan(ctx, field, value, s.value); err == nil {
if sameElemType { if sameElemType {
field.ReflectValueOf(ctx, value).Set(reflect.ValueOf(s.Serializer).Elem()) field.ReflectValueOf(ctx, value).Set(reflect.ValueOf(s.Serializer).Elem())
s.Serializer = reflect.New(reflect.Indirect(reflect.ValueOf(field.Serializer)).Type()).Interface().(SerializerInterface)
} else if sameType { } else if sameType {
field.ReflectValueOf(ctx, value).Set(reflect.ValueOf(s.Serializer)) field.ReflectValueOf(ctx, value).Set(reflect.ValueOf(s.Serializer))
s.Serializer = reflect.New(reflect.Indirect(reflect.ValueOf(field.Serializer)).Type()).Interface().(SerializerInterface)
} }
si := reflect.New(serializerType)
si.Elem().Set(serializerValue)
s.Serializer = si.Interface().(SerializerInterface)
} }
} else { } else {
err = oldFieldSetter(ctx, value, v) err = oldFieldSetter(ctx, value, v)
@ -939,11 +942,15 @@ func (field *Field) setupValuerAndSetter() {
func (field *Field) setupNewValuePool() { func (field *Field) setupNewValuePool() {
if field.Serializer != nil { if field.Serializer != nil {
serializerValue := reflect.Indirect(reflect.ValueOf(field.Serializer))
serializerType := serializerValue.Type()
field.NewValuePool = &sync.Pool{ field.NewValuePool = &sync.Pool{
New: func() interface{} { New: func() interface{} {
si := reflect.New(serializerType)
si.Elem().Set(serializerValue)
return &serializer{ return &serializer{
Field: field, Field: field,
Serializer: field.Serializer, Serializer: si.Interface().(SerializerInterface),
} }
}, },
} }

View File

@ -9,11 +9,12 @@ require (
github.com/lib/pq v1.10.7 github.com/lib/pq v1.10.7
github.com/mattn/go-sqlite3 v1.14.16 // indirect github.com/mattn/go-sqlite3 v1.14.16 // indirect
github.com/microsoft/go-mssqldb v0.20.0 // indirect github.com/microsoft/go-mssqldb v0.20.0 // indirect
golang.org/x/crypto v0.7.0 // indirect
gorm.io/driver/mysql v1.4.7 gorm.io/driver/mysql v1.4.7
gorm.io/driver/postgres v1.4.8 gorm.io/driver/postgres v1.4.8
gorm.io/driver/sqlite v1.4.4 gorm.io/driver/sqlite v1.4.4
gorm.io/driver/sqlserver v1.4.2 gorm.io/driver/sqlserver v1.4.2
gorm.io/gorm v1.24.5 gorm.io/gorm v1.24.6
) )
replace gorm.io/gorm => ../ replace gorm.io/gorm => ../