Fix inconsistent calculation of goroutines.

We observed that sometimes the `pprof.Lookup("goroutine")` resulted in a different goroutine count than `runtime.NumGoroutine()`. It might be due to a race condition, but our usage of both made it impossible to debug.
This commit is contained in:
Maximilian Paß
2023-11-14 23:52:51 +01:00
parent 7a446fee26
commit 2ea24911de

View File

@ -7,8 +7,10 @@ import (
"github.com/stretchr/testify/suite" "github.com/stretchr/testify/suite"
"io" "io"
"os" "os"
"regexp"
"runtime" "runtime"
"runtime/pprof" "runtime/pprof"
"strconv"
"time" "time"
) )
@ -23,6 +25,8 @@ func ChannelReceivesSomething(ch chan bool, timeout time.Duration) bool {
} }
} }
var numGoroutines = regexp.MustCompile(`^goroutine profile: total (\d*)\n`)
// MemoryLeakTestSuite adds an assertion for checking Goroutine leaks. // MemoryLeakTestSuite adds an assertion for checking Goroutine leaks.
// Be aware not to overwrite the SetupTest or TearDownTest function! // Be aware not to overwrite the SetupTest or TearDownTest function!
type MemoryLeakTestSuite struct { type MemoryLeakTestSuite struct {
@ -35,12 +39,21 @@ type MemoryLeakTestSuite struct {
} }
func (s *MemoryLeakTestSuite) SetupTest() { func (s *MemoryLeakTestSuite) SetupTest() {
s.goroutineCountBefore = runtime.NumGoroutine()
s.ExpectedGoroutingIncrease = 0 s.ExpectedGoroutingIncrease = 0
s.goroutinesBefore = &bytes.Buffer{} s.goroutinesBefore = &bytes.Buffer{}
err := pprof.Lookup("goroutine").WriteTo(s.goroutinesBefore, 1) err := pprof.Lookup("goroutine").WriteTo(s.goroutinesBefore, 1)
s.NoError(err) s.Require().NoError(err)
match := numGoroutines.FindSubmatch(s.goroutinesBefore.Bytes())
if match == nil {
s.Fail("gouroutines could not be parsed: " + s.goroutinesBefore.String())
}
// We do not use runtime.NumGoroutine() to not create inconsistency to the Lookup.
s.goroutineCountBefore, err = strconv.Atoi(string(match[1]))
if err != nil {
s.Fail("number of goroutines could not be parsed: " + err.Error())
}
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
s.TestCtx = ctx s.TestCtx = ctx