diff options
-rw-r--r-- | src/database/sql/sql.go | 12 |
1 files changed, 9 insertions, 3 deletions
diff --git a/src/database/sql/sql.go b/src/database/sql/sql.go index 89976c7fd0..97f4016fbd 100644 --- a/src/database/sql/sql.go +++ b/src/database/sql/sql.go @@ -1769,14 +1769,20 @@ func (tx *Tx) closePrepared() { // Commit commits the transaction. func (tx *Tx) Commit() error { - if !atomic.CompareAndSwapInt32(&tx.done, 0, 1) { - return ErrTxDone - } + // Check context first to avoid transaction leak. + // If put it behind tx.done CompareAndSwap statement, we cant't ensure + // the consistency between tx.done and the real COMMIT operation. select { default: case <-tx.ctx.Done(): + if atomic.LoadInt32(&tx.done) == 1 { + return ErrTxDone + } return tx.ctx.Err() } + if !atomic.CompareAndSwapInt32(&tx.done, 0, 1) { + return ErrTxDone + } var err error withLock(tx.dc, func() { err = tx.txi.Commit() |