diff --git a/mvcc/backend/batch_tx.go b/mvcc/backend/batch_tx.go index 2cafb9f7e5fd..e4356e6ff42d 100644 --- a/mvcc/backend/batch_tx.go +++ b/mvcc/backend/batch_tx.go @@ -166,19 +166,12 @@ func (t *batchTx) commit(stop bool) { t.backend.mu.RLock() defer t.backend.mu.RUnlock() - // 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()) - } + // t.tx.DB()==nil if 'CommitAndStop' calls 'batchTx.commit(true)', + // which initializes *bolt.Tx.db and *bolt.Tx.meta as nil; panics t.tx.Size() + // server-side must make sure 'batchTx.commit(false)' does not follow + // 'batchTx.commit(true)' (e.g. stopping backend, and inflight Hash call). + // etcdserver ensures that all inflight gRPC requests are handled via 'GracefulStop' + atomic.StoreInt64(&t.backend.size, t.tx.Size()) return }