fortytw2 / leaktest Goto Github PK
View Code? Open in Web Editor NEWGoroutine Leak Detector
License: BSD 3-Clause "New" or "Revised" License
Goroutine Leak Detector
License: BSD 3-Clause "New" or "Revised" License
As per the change in Cockroach leaktest I'd like to ignore HTTP keep-alives in this utility.
leaktest: ignore HTTP keep alives
Tests that performed an HTTP connection using the default client had to
have a special instruction to poke http.DefaultClient to disable keep
alives to prevent the leaktester from failing. An upcoming change performs
an HTTP connection with its own unconfigurable client, which would have
required a bunch of special code just to make the leak tester pass.
Instead, ignore stacks that are included during a connection in keep
alive. This matches the code in net/http/main_test.go#afterTest.
cockroachdb/cockroach@e5e6dde#diff-fdc7f75e12e2453349457c6742ff532f
I'm seeing a mysterious issue when I use leaktest in combination with a high -count flag, as in:
go test -run . -failfast -count 100 --tags=unit ./...
leaktest.go:83: leaktest: error parsing stack: "goro"
FAIL
The reported line number in leaktest.go is always the same. But the exact string it's failing to parse changes from run to run. e.g.
leaktest.go:83: leaktest: error parsing stack: "gorouti"
leaktest.go:83: leaktest: error parsing stack: "goroutine 99673 [select]:"
It seems to happen more predictably when I run with high -count values.
Any ideas what could be causing this?
Here is my go build env:
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/marshall/.cache/go-build"
GOENV="/home/marshall/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/marshall/code/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/lib/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="x86_64-pc-linux-gnu-gcc"
CXX="x86_64-pc-linux-gnu-g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build261227009=/tmp/go-build -gno-record-gcc-switches"
It appears that since the context.WithTimeout
is called at the beginning of the test, tests which take longer than timeout
to complete automatically fail. This is because the Done
channel on the context is already closed by time the test completes. This is problematic for tests which take an non-deterministic amount of time to complete.
I would have expected the timeout value to be the amount of time leaktest waits when the deferred function is executed, not from the moment Check
is called.
Currently we are getting around the issue by wrapping leaktest functionality:
func CheckTimeout(t *testing.T, dur time.Duration) func() {
ctx, cancel := context.WithCancel(context.Background())
fn := leaktest.CheckContext(ctx, t)
return func() {
time.AfterFunc(dur, cancel)
fn()
}
}
I can install other go projects, but for this one I get this error:
$ go install github.com/becheran/roumon@latest
go: downloading github.com/becheran/roumon v1.2.0
go: github.com/becheran/roumon@latest: github.com/becheran/[email protected]: verifying module: github.com/becheran/[email protected]: Get "https://sum.golang.org/lookup/github.com/becheran/[email protected]": write tcp [fe80::6e7e:67ff:fedc:d035%utun4]:52931->[2607:f8b0:4005:811::2011]:443: write: socket is not connected
Example in README should be
func TestPool(t *testing.T) {
defer leaktest.Check(t)()
go func() {
for {
time.Sleep(time.Second)
}
}()
}
Notice the () after the } at the end of the go function -- Just a typo I am certain.
See https://travis-ci.org/bep/debounce
I don't understand why a leak is reported on tip, but not on <= Go 1.6.
leaktest does not play well with go test -timeout=5s
. Regardless, waiting 5 seconds for goroutines to shut down seems excessive. My expectation was that goroutines would be checked as soon as the deferred function was called.
I suggest adding an optional timeout argument to Check
, or providing some other way of delaying the check. Note that if Check
did not delay by default, you could implement this behavior yourself:
func TestFoo(t testing.T) {
checkFn := leaktest.Check(t)
defer func() {
time.Sleep(5 * time.Second)
checkFn()
}()
}
Furthermore, this would give you more fine-grained control over when the check executes. For example, you could wait on a channel before checking. The only reason I propose adding an optional timeout argument is because it seems like a common case.
Hello!
Thanks for this library, it'll definitely come in handy. Would you be able to document the reasons why t.Parallel isn't supported and what ideas you have for addressing the problem?
Thanks
With Go 1.7, there is always a leaked Gorouting reported, even for empty tests:
func TestStoppedSlotReporter(t *testing.T) {
defer leaktest.Check(t)()
}
defer leaktest.Check(t)
is surprisingly incorrect and does nothing. Lets investigate ways to detect when this happens and inform the caller, otherwise they may think that their code is leak free and dandy when it really isn't
Given that golang is garbage-collected, I'm trying to understand instances when it would make sense to use this package. As such, I tried to simulate a memory leak.
func TestGoRoutineLeak(t *testing.T) {
leaktest.Check(t)()
c := make (chan int,0)
go func () {
for _ = range c{
}
}()
}
This doesn't throw any errors? I was expecting it to throw an error since we're leaking a goroutine in plain sight. I'd love a pointer or two in the right direction here.
Thanks :)
Architecture: aarch64
Golang version: 1.8.3
OS: Fedora 26
Same tests fail for other architectures randomly. Could not reproduce for those other arches though.
go test -compiler gc -ldflags '' github.com/fortytw2/leaktest
unexpected fault address 0x117160
fatal error: fault
[signal SIGSEGV: segmentation violation code=0x2 addr=0x117160 pc=0x117160]
goroutine 18 [running]:
runtime.throw(0x147168, 0x5)
/usr/lib/golang/src/runtime/panic.go:596 +0x70 fp=0x4420040eb0 sp=0x4420040e90
runtime.sigpanic()
/usr/lib/golang/src/runtime/signal_unix.go:297 +0x224 fp=0x4420040f00 sp=0x4420040eb0
github.com/fortytw2/leaktest.CheckTimeout.func1()
/builddir/build/BUILDROOT/golang-github-fortytw2-leaktest-1.1.0-1.fc26.aarch64/usr/share/gocode/src/github.com/fortytw2/leaktest/leaktest.go:75 +0x38 fp=0x4420040f20 sp=0x4420040f10
github.com/fortytw2/leaktest.TestCheck(0x4420078270)
/builddir/build/BUILDROOT/golang-github-fortytw2-leaktest-1.1.0-1.fc26.aarch64/usr/share/gocode/src/github.com/fortytw2/leaktest/leaktest_test.go:73 +0xb0 fp=0x4420040fa0 sp=0x4420040f20
testing.tRunner(0x4420078270, 0x150138)
/usr/lib/golang/src/testing/testing.go:657 +0x84 fp=0x4420040fc0 sp=0x4420040fa0
runtime.goexit()
/usr/lib/golang/src/runtime/asm_arm64.s:981 +0x4 fp=0x4420040fc0 sp=0x4420040fc0
created by testing.(*T).Run
/usr/lib/golang/src/testing/testing.go:697 +0x240
goroutine 1 [chan receive]:
testing.(*T).Run(0x44200781a0, 0x147b6e, 0x9, 0x150138, 0x60)
/usr/lib/golang/src/testing/testing.go:698 +0x260
testing.runTests.func1(0x44200781a0)
/usr/lib/golang/src/testing/testing.go:882 +0x58
testing.tRunner(0x44200781a0, 0x442003fde0)
/usr/lib/golang/src/testing/testing.go:657 +0x84
testing.runTests(0x4420086980, 0x1f1480, 0x2, 0x2, 0x14b00a)
/usr/lib/golang/src/testing/testing.go:888 +0x260
testing.(*M).Run(0x442003ff28, 0x442003ff28)
/usr/lib/golang/src/testing/testing.go:822 +0xe0
main.main()
github.com/fortytw2/leaktest/_test/_testmain.go:44 +0xe0
goroutine 20 [sleep]:
time.Sleep(0x3b9aca00)
/usr/lib/golang/src/runtime/time.go:59 +0xe8
github.com/fortytw2/leaktest.glob..func1()
/builddir/build/BUILDROOT/golang-github-fortytw2-leaktest-1.1.0-1.fc26.aarch64/usr/share/gocode/src/github.com/fortytw2/leaktest/leaktest_test.go:25 +0x20
created by github.com/fortytw2/leaktest.TestCheck
/builddir/build/BUILDROOT/golang-github-fortytw2-leaktest-1.1.0-1.fc26.aarch64/usr/share/gocode/src/github.com/fortytw2/leaktest/leaktest_test.go:71 +0xa4
goroutine 37 [chan receive]:
github.com/fortytw2/leaktest.glob..func2()
/builddir/build/BUILDROOT/golang-github-fortytw2-leaktest-1.1.0-1.fc26.aarch64/usr/share/gocode/src/github.com/fortytw2/leaktest/leaktest_test.go:32 +0x48
created by github.com/fortytw2/leaktest.TestCheck
/builddir/build/BUILDROOT/golang-github-fortytw2-leaktest-1.1.0-1.fc26.aarch64/usr/share/gocode/src/github.com/fortytw2/leaktest/leaktest_test.go:71 +0xa4
FAIL github.com/fortytw2/leaktest 2.078s
The latest release was tagged over a year ago. How would you feel about tagging releases more frequently?
Hello! I've create a minial step to create a condition of a leaked goroutine. In this case, the test never finishes.
I think I've narrowed the bug down to this line where it seems to block.
My guess is, because this goroutine never blocks and runtime.Stack()
is waiting for the goroutine to block?
package hub
import (
"testing"
"time"
"github.com/fortytw2/leaktest"
)
func TestInfiniteLoop(t *testing.T) {
defer leaktest.CheckTimeout(t, time.Second)()
go func() {
i := 0
for {
i++
}
}()
}
go version go1.9 linux/amd64
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/anthony/go"
GORACE=""
GOROOT="/usr/local/go"
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build343347876=/tmp/go-build -gno-record-gcc-switches"
CXX="g++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOROOT/bin/go version: go version go1.9 linux/amd64
GOROOT/bin/go tool compile -V: compile version go1.9
uname -sr: Linux 4.10.0-40-generic
Distributor ID: Ubuntu
Description: Ubuntu 16.04.3 LTS
Release: 16.04
Codename: xenial
/lib/x86_64-linux-gnu/libc.so.6: GNU C Library (Ubuntu GLIBC 2.23-0ubuntu9) stable release version 2.23, by Roland McGrath et al.
gdb --version: GNU gdb (Ubuntu 7.11.1-0ubuntu1~16.5) 7.11.1
Ones from here http://play.golang.org/p/g0L28Rove3 linked from golang/go#12989
Please consider adding Go modules support by running "go mod init github.com/fortytw2/leaktest" and committing the resulting go.mod
file.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.