Browse Source

backend: skip *bolt.DB.Size call when nil

Fix https://github.com/coreos/etcdlabs/issues/30.
Gyu-Ho Lee 9 years ago
parent
commit
7d30326968
1 changed files with 14 additions and 1 deletions
  1. 14 1
      mvcc/backend/batch_tx.go

+ 14 - 1
mvcc/backend/batch_tx.go

@@ -162,7 +162,20 @@ func (t *batchTx) commit(stop bool) {
 		if t.pending == 0 && !stop {
 		if t.pending == 0 && !stop {
 			t.backend.mu.RLock()
 			t.backend.mu.RLock()
 			defer t.backend.mu.RUnlock()
 			defer t.backend.mu.RUnlock()
-			atomic.StoreInt64(&t.backend.size, t.tx.Size())
+
+			// batchTx.commit(true) calls *bolt.Tx.Commit, which
+			// initializes *bolt.Tx.db and *bolt.Tx.meta as nil,
+			// and subsequent *bolt.Tx.Size() call panics.
+			//
+			// This nil pointer reference panic happens when:
+			//   1. batchTx.commit(false) from newBatchTx
+			//   2. batchTx.commit(true) from stopping backend
+			//   3. batchTx.commit(false) from inflight mvcc Hash call
+			//
+			// Check if db is nil to prevent this panic
+			if t.tx.DB() != nil {
+				atomic.StoreInt64(&t.backend.size, t.tx.Size())
+			}
 			return
 			return
 		}
 		}
 		start := time.Now()
 		start := time.Now()