@@ -20,6 +20,7 @@ import (
20
20
"math"
21
21
"math/rand"
22
22
"sync"
23
+ "sync/atomic"
23
24
"testing"
24
25
"time"
25
26
@@ -594,3 +595,57 @@ func TestAllocComputationIssue(t *testing.T) {
594
595
require .Equal (t , int64 (7 ), min )
595
596
require .Equal (t , int64 (13 ), max )
596
597
}
598
+
599
+ func TestIssue40584 (t * testing.T ) {
600
+ store , err := mockstore .NewMockStore ()
601
+ require .NoError (t , err )
602
+ defer func () {
603
+ err := store .Close ()
604
+ require .NoError (t , err )
605
+ }()
606
+
607
+ ctx := kv .WithInternalSourceType (context .Background (), kv .InternalTxnMeta )
608
+ err = kv .RunInNewTxn (ctx , store , false , func (ctx context.Context , txn kv.Transaction ) error {
609
+ m := meta .NewMeta (txn )
610
+ err = m .CreateDatabase (& model.DBInfo {ID : 1 , Name : model .NewCIStr ("a" )})
611
+ require .NoError (t , err )
612
+ err = m .CreateTableOrView (1 , & model.TableInfo {ID : 1 , Name : model .NewCIStr ("t" )})
613
+ require .NoError (t , err )
614
+ return nil
615
+ })
616
+ require .NoError (t , err )
617
+
618
+ alloc := autoid .NewAllocator (store , 1 , 1 , false , autoid .RowIDAllocType )
619
+ require .NotNil (t , alloc )
620
+
621
+ finishAlloc := make (chan bool )
622
+ finishBase := make (chan bool )
623
+ var done int32 = 0
624
+
625
+ // call allocator.Alloc and allocator.Base in parallel for 3 seconds to detect data race
626
+ go func () {
627
+ for {
628
+ alloc .Alloc (ctx , 1 , 1 , 1 )
629
+ if atomic .LoadInt32 (& done ) > 0 {
630
+ break
631
+ }
632
+ }
633
+ finishAlloc <- true
634
+ }()
635
+
636
+ go func () {
637
+ for {
638
+ alloc .Base ()
639
+ if atomic .LoadInt32 (& done ) > 0 {
640
+ break
641
+ }
642
+ }
643
+ finishBase <- true
644
+ }()
645
+
646
+ runTime := time .NewTimer (time .Second * 3 )
647
+ <- runTime .C
648
+ atomic .AddInt32 (& done , 1 )
649
+ <- finishAlloc
650
+ <- finishBase
651
+ }
0 commit comments