Skip to content

Commit 82d1924

Browse files
ti-chi-botbufferfliesokJiangti-chi-bot[bot]
authored andcommitted
region: fix the potential panic . (tikv#7143) (tikv#8916)
close tikv#8915 Signed-off-by: ti-chi-bot <ti-community-prow-bot@tidb.io> Signed-off-by: 童剑 <1045931706@qq.com> Co-authored-by: buffer <1045931706@qq.com> Co-authored-by: 童剑 <1045931706@qq.com> Co-authored-by: okJiang <819421878@qq.com> Co-authored-by: ti-chi-bot[bot] <108142056+ti-chi-bot[bot]@users.noreply.github.com>
1 parent 2940bb5 commit 82d1924

File tree

2 files changed

+31
-2
lines changed

2 files changed

+31
-2
lines changed

server/core/region.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,13 @@ import (
2222
"sort"
2323
"strings"
2424
"sync/atomic"
25+
"time"
2526
"unsafe"
2627

2728
"github.com/docker/go-units"
2829
"github.com/gogo/protobuf/proto"
2930
"github.com/pingcap/errors"
31+
"github.com/pingcap/failpoint"
3032
"github.com/pingcap/kvproto/pkg/metapb"
3133
"github.com/pingcap/kvproto/pkg/pdpb"
3234
"github.com/pingcap/kvproto/pkg/replication_modepb"
@@ -886,6 +888,11 @@ func (r *RegionsInfo) setRegionLocked(region *RegionInfo) (*RegionInfo, []*Regio
886888

887889
// UpdateSubTree updates the subtree.
888890
func (r *RegionsInfo) UpdateSubTree(region, origin *RegionInfo, toRemove []*RegionInfo, rangeChanged bool) {
891+
failpoint.Inject("UpdateSubTree", func() {
892+
if origin == nil {
893+
time.Sleep(time.Second)
894+
}
895+
})
889896
r.st.Lock()
890897
defer r.st.Unlock()
891898
if origin != nil {
@@ -894,8 +901,17 @@ func (r *RegionsInfo) UpdateSubTree(region, origin *RegionInfo, toRemove []*Regi
894901
// TODO: Improve performance by deleting only the different peers.
895902
r.removeRegionFromSubTreeLocked(origin)
896903
} else {
897-
r.updateSubTreeStat(origin, region)
898-
r.subRegions[region.GetID()].RegionInfo = region
904+
// The region tree and the subtree update is not atomic and the region tree is updated first.
905+
// If there are two thread needs to update region tree,
906+
// t1: thread-A update region tree
907+
// t2: thread-B: update region tree again
908+
// t3: thread-B: update subtree
909+
// t4: thread-A: update region subtree
910+
// to keep region tree consistent with subtree, we need to drop this update.
911+
if tree, ok := r.subRegions[region.GetID()]; ok {
912+
r.updateSubTreeStat(origin, region)
913+
tree.RegionInfo = region
914+
}
899915
return
900916
}
901917
}

server/core/region_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"testing"
2323
"time"
2424

25+
"github.com/pingcap/failpoint"
2526
"github.com/pingcap/kvproto/pkg/metapb"
2627
"github.com/pingcap/kvproto/pkg/pdpb"
2728
"github.com/stretchr/testify/require"
@@ -451,6 +452,18 @@ func TestRegionKey(t *testing.T) {
451452
}
452453
}
453454

455+
func TestSetRegionConcurrence(t *testing.T) {
456+
re := require.New(t)
457+
re.NoError(failpoint.Enable("github.com/tikv/pd/pkg/core/UpdateSubTree", `return()`))
458+
regions := NewRegionsInfo()
459+
region := NewTestRegionInfo([]byte("a"), []byte("b"))
460+
go func() {
461+
regions.AtomicCheckAndPutRegion(region)
462+
}()
463+
regions.AtomicCheckAndPutRegion(region)
464+
re.NoError(failpoint.Disable("github.com/tikv/pd/pkg/core/UpdateSubTree"))
465+
}
466+
454467
func TestSetRegion(t *testing.T) {
455468
re := require.New(t)
456469
regions := NewRegionsInfo()

0 commit comments

Comments
 (0)