Skip to content

Transaction leak using Session in Scopes #7592

@horror-proton

Description

@horror-proton

GORM Playground Link

go-gorm/playground#831

Description

InstanceSet can return a new instance

gorm/gorm.go

Lines 376 to 381 in b881483

// InstanceSet store value with key into current db instance's context
func (db *DB) InstanceSet(key string, value interface{}) *DB {
tx := db.getInstance()
tx.Statement.Settings.Store(fmt.Sprintf("%p", tx.Statement)+key, value)
return tx
}

which is discarded in BeginTransaction

db.InstanceSet("gorm:started_transaction", true)

In most cases, db.clone = 0, db == tx so it works fine.
go-gorm/playground#831
While here db.clone = 2 for some reason, so an actual clone happens, CommitOrRollbackTransaction was not able to observe the key "gorm:started_transaction", and the commit was never executed.

Is nesting Session with Scopes supported? Perhaps it will be better to add an asserting here instead of continuing quietly.

> gorm.io/gorm.(*DB).InstanceSet() /home/arch/go/pkg/mod/gorm.io/gorm@v1.30.0/gorm.go:370 (PC: 0x80373d)
Frame 0: /home/arch/go/pkg/mod/gorm.io/gorm@v1.30.0/gorm.go:370 (PC: 80373d)
   365: }
   366:
   367: // InstanceSet store value with key into current db instance's context
   368: func (db *DB) InstanceSet(key string, value interface{}) *DB {
   369:         tx := db.getInstance()
=> 370:         tx.Statement.Settings.Store(fmt.Sprintf("%p", tx.Statement)+key, value)
   371:         return tx
   372: }
   373:
   374: // InstanceGet get value with key from current db instance's context
   375: func (db *DB) InstanceGet(key string) (interface{}, bool) {
(dlv) print &tx.Statement.Settings
(*sync.Map)(0xc0002240e0)
(dlv) print &db.Statement.Settings
(*sync.Map)(0xc0001362c0)
(dlv) print db.clone
2

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions