aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/database/sql/sql.go12
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()