From 836bd6bc3a7669b25169b4d666c404ad1cdc751f Mon Sep 17 00:00:00 2001 From: ahrtr Date: Sun, 3 Apr 2022 06:01:10 +0800 Subject: [PATCH] fix WARNING: DATA RACE issue when multiple goroutines access the backend concurrently --- server/etcdserver/adapters.go | 8 ++++++++ server/etcdserver/server.go | 6 +++--- server/etcdserver/v3_server.go | 4 ++++ server/storage/backend/backend.go | 2 ++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/server/etcdserver/adapters.go b/server/etcdserver/adapters.go index c3a17c6ee20..9511bc6a6ac 100644 --- a/server/etcdserver/adapters.go +++ b/server/etcdserver/adapters.go @@ -74,6 +74,10 @@ func (s *serverVersionAdapter) GetMembersVersions() map[string]*version.Versions } func (s *serverVersionAdapter) GetStorageVersion() *semver.Version { + // `applySnapshot` sets a new backend instance, so we need to acquire the bemu lock. + s.bemu.RLock() + defer s.bemu.RUnlock() + tx := s.be.BatchTx() tx.Lock() defer tx.Unlock() @@ -85,6 +89,10 @@ func (s *serverVersionAdapter) GetStorageVersion() *semver.Version { } func (s *serverVersionAdapter) UpdateStorageVersion(target semver.Version) error { + // `applySnapshot` sets a new backend instance, so we need to acquire the bemu lock. + s.bemu.RLock() + defer s.bemu.RUnlock() + tx := s.be.BatchTx() tx.Lock() defer tx.Unlock() diff --git a/server/etcdserver/server.go b/server/etcdserver/server.go index e925f47d450..f5632318eab 100644 --- a/server/etcdserver/server.go +++ b/server/etcdserver/server.go @@ -256,7 +256,7 @@ type EtcdServer struct { kv mvcc.WatchableKV lessor lease.Lessor - bemu sync.Mutex + bemu sync.RWMutex be backend.Backend beHooks *serverstorage.BackendHooks authStore auth.AuthStore @@ -2229,8 +2229,8 @@ func (s *EtcdServer) parseProposeCtxErr(err error, start time.Time) error { func (s *EtcdServer) KV() mvcc.WatchableKV { return s.kv } func (s *EtcdServer) Backend() backend.Backend { - s.bemu.Lock() - defer s.bemu.Unlock() + s.bemu.RLock() + defer s.bemu.RUnlock() return s.be } diff --git a/server/etcdserver/v3_server.go b/server/etcdserver/v3_server.go index 3e868bebda9..7da9a2c4d04 100644 --- a/server/etcdserver/v3_server.go +++ b/server/etcdserver/v3_server.go @@ -237,7 +237,11 @@ func (s *EtcdServer) Compact(ctx context.Context, r *pb.CompactionRequest) (*pb. // the hash may revert to a hash prior to compaction completing // if the compaction resumes. Force the finished compaction to // commit so it won't resume following a crash. + // + // `applySnapshot` sets a new backend instance, so we need to acquire the bemu lock. + s.bemu.RLock() s.be.ForceCommit() + s.bemu.RUnlock() trace.Step("physically apply compaction") } if err != nil { diff --git a/server/storage/backend/backend.go b/server/storage/backend/backend.go index c558ecacd68..67cfab9dd3a 100644 --- a/server/storage/backend/backend.go +++ b/server/storage/backend/backend.go @@ -419,6 +419,8 @@ func (b *backend) run() { func (b *backend) Close() error { close(b.stopc) <-b.donec + b.mu.Lock() + defer b.mu.Unlock() return b.db.Close() }