浏览代码

lib/db: Don't leak snapshot when closing (#6331)

We could potentially get a snapshot and then fail to get a releaser,
leaking the snapshot. This takes the releaser first and makes sure to
release it on snapshot error.
Jakob Borg 5 年之前
父节点
当前提交
d95a087829
共有 1 个文件被更改,包括 10 次插入8 次删除
  1. 10 8
      lib/db/backend/leveldb_backend.go

+ 10 - 8
lib/db/backend/leveldb_backend.go

@@ -37,14 +37,15 @@ func (b *leveldbBackend) NewReadTransaction() (ReadTransaction, error) {
 }
 
 func (b *leveldbBackend) newSnapshot() (leveldbSnapshot, error) {
-	snap, err := b.ldb.GetSnapshot()
-	if err != nil {
-		return leveldbSnapshot{}, wrapLeveldbErr(err)
-	}
 	rel, err := newReleaser(b.closeWG)
 	if err != nil {
 		return leveldbSnapshot{}, err
 	}
+	snap, err := b.ldb.GetSnapshot()
+	if err != nil {
+		rel.Release()
+		return leveldbSnapshot{}, wrapLeveldbErr(err)
+	}
 	return leveldbSnapshot{
 		snap: snap,
 		rel:  rel,
@@ -52,14 +53,15 @@ func (b *leveldbBackend) newSnapshot() (leveldbSnapshot, error) {
 }
 
 func (b *leveldbBackend) NewWriteTransaction() (WriteTransaction, error) {
-	snap, err := b.newSnapshot()
-	if err != nil {
-		return nil, err // already wrapped
-	}
 	rel, err := newReleaser(b.closeWG)
 	if err != nil {
 		return nil, err
 	}
+	snap, err := b.newSnapshot()
+	if err != nil {
+		rel.Release()
+		return nil, err // already wrapped
+	}
 	return &leveldbTransaction{
 		leveldbSnapshot: snap,
 		ldb:             b.ldb,