@@ -19,6 +19,9 @@ package testkit
19
19
import (
20
20
"context"
21
21
"fmt"
22
+ "log"
23
+ "os"
24
+ "runtime/pprof"
22
25
"strings"
23
26
"sync"
24
27
"testing"
@@ -684,3 +687,34 @@ func buildRowsRecordSet(ctx context.Context, rs sqlexec.RecordSet) sqlexec.Recor
684
687
idx : 0 ,
685
688
}
686
689
}
690
+
691
+ // DebugDumpOnTimeout will dump stack traces and possible blockers after given timeout.
692
+ // wg is the WaitGroup to mark as done when finished (to avoid runaway goroutines)
693
+ // c is the channel that will signal or close to cancel the timeout.
694
+ func DebugDumpOnTimeout (wg * sync.WaitGroup , c chan struct {}, d time.Duration ) {
695
+ select {
696
+ case <- time .After (d ):
697
+ log .Print ("Injected timeout, dumping all goroutines:" )
698
+ _ = pprof .Lookup ("goroutine" ).WriteTo (os .Stdout , 2 )
699
+ log .Print ("dumping all stack traces led to possible block:" )
700
+ _ = pprof .Lookup ("block" ).WriteTo (os .Stdout , 2 )
701
+ log .Print ("dumping all stack traces holding mutexes:" )
702
+ _ = pprof .Lookup ("mutex" ).WriteTo (os .Stdout , 2 )
703
+ log .Print ("dumping all stack traces led to creation of new OS threads:" )
704
+ _ = pprof .Lookup ("threadcreate" ).WriteTo (os .Stdout , 2 )
705
+ log .Print ("Waiting 2 seconds and to see if things changed..." )
706
+ time .Sleep (2 * time .Second )
707
+ log .Print ("Injected timeout, dumping all goroutines:" )
708
+ _ = pprof .Lookup ("goroutine" ).WriteTo (os .Stdout , 2 )
709
+ log .Print ("dumping all stack traces led to possible block:" )
710
+ _ = pprof .Lookup ("block" ).WriteTo (os .Stdout , 2 )
711
+ log .Print ("dumping all stack traces holding mutexes:" )
712
+ _ = pprof .Lookup ("mutex" ).WriteTo (os .Stdout , 2 )
713
+ log .Print ("dumping all stack traces led to creation of new OS threads:" )
714
+ _ = pprof .Lookup ("threadcreate" ).WriteTo (os .Stdout , 2 )
715
+ panic ("Injected timeout" )
716
+ case <- c :
717
+ // Test finished
718
+ }
719
+ wg .Done ()
720
+ }
0 commit comments