Goroutine leak detector

goleak GoDoc Build Status Coverage Status

Goroutine leak detector to help avoid Goroutine leaks.

Installation

You can use go get to get the latest version:

go get -u go.uber.org/goleak

goleak also supports semver releases. It is compatible with Go 1.5+.

Quick Start

To verify that there are no unexpected goroutines running at the end of a test:

func TestA(t *testing.T) {
	defer goleak.VerifyNone(t)

	// test logic here.
}

Instead of checking for leaks at the end of every test, goleak can also be run at the end of every test package by creating a TestMain function for your package:

func TestMain(m *testing.M) {
	goleak.VerifyTestMain(m)
}

Determine Source of Package Leaks

When verifying leaks using TestMain, the leak test is only run once after all tests have been run. This is typically enough to ensure there's no goroutines leaked from tests, but when there are leaks, it's hard to determine which test is causing them.

You can use the following bash script to determine the source of the failing test:

# Create a test binary which will be used to run each test individually
$ go test -c -o tests

# Run each test individually, printing "." for successful tests, or the test name
# for failing tests.
$ for test in $(go test -list . | grep -E "^(Test|Example)"); do ./tests -test.run "^$test\$" &>/dev/null && echo -n "." || echo "\n$test failed"; done

This will only print names of failing tests which can be investigated individually. E.g.,

.....
TestLeakyTest failed
.......

Stability

goleak is v1 and follows SemVer strictly.

No breaking changes will be made to exported APIs before 2.0.

Owner
Uber Go
Uber's open source software for Go development
Uber Go
Comments
  • Support t.Parallel?

    Support t.Parallel?

    Hi, thanks for providing great package :)

    BTW, I saw goleak internal source and found below switch...case: https://github.com/uber-go/goleak/blob/18742541d022941d2ef0db05d30bc68f69e96bd9/options.go#L118

    But, I used t.Parallel func on my project testing. So, goleak suggested:

    found unexpected goroutines
    

    Is it the expected behavior? Or, Should I adding goleak.IgnoreTopFunction("testing.(*T).Parallel") to defer goleak.VerifyNoLeaks(t)? (and, is it correct use case?)

  • support register teardown function in VerifyTestMain

    support register teardown function in VerifyTestMain

    TestMain can be used for setup and teardown logic. However, VerifyTestMain calls os.Exit which disables to register teardown function by defer. cc @prashantv

  • CVE-2020-14040: imports golang.org/x/tools > golang.org/x/net > golang.org/x/text

    CVE-2020-14040: imports golang.org/x/tools > golang.org/x/net > golang.org/x/text

    This PR imports an updated version of golang.org/x/tools. x/tools imports x/net which imports x/text which includes the bug outlined in CVE-2020-14040.

    With the update of x/net it also fixes CVE-2020-9283 in the golang.org/x/crypto package/module.

  • Mark VerifyNone as a test Helper

    Mark VerifyNone as a test Helper

    Mark VerifyNone(...) as a test Helper function, so that it reports the error at the call site, rather than leaks.go:78:.

    From the go docs:

    Helper marks the calling function as a test helper function. When printing file and line information, that function will be skipped. Helper may be called simultaneously from multiple goroutines.

    This is useful for tests that verify go routines at multiple points, so failures can be more easily distinguished.

  • Add option to pass teardown function

    Add option to pass teardown function

    Hi!

    In some cases performing additional work after test execution are required. But when VerifyTestMain is used it is not possible to do this work before leaked goroutine caught. This may be related to goroutine shutdown, so it should be done inside VerifyTestMain after test run but before check.

    This PR adds option to pass custom teardown function.

  • Fix flaky tests

    Fix flaky tests

    Some tests assume that stack.All() will give a stable set of goroutines: that any background goroutines from the test framework/previous tests have run till they're blocked.

    Add verification that stack.All() returns a "stable" set of stacks before running these tests.

  • Upgrade stretchr/testify

    Upgrade stretchr/testify

    Hello,

    I am working at Manomano and we use gemnasium analyser to report securities issues.

    We use zap logger and goleak is a dependency of zap.logger. This little pr purpose you to update your yaml dependency to a fixed version. Detail report: | Severity | Unknown | | Identifier | | | URL | https://github.com/docker/cli/pull/2117 | | Scanner | Gemnasium | | Message | XML Entity Expansion in gopkg.in/yaml.v2 | | Package | gopkg.in/yaml.v2 v2.2.1 | | Solution | Upgrade to version 2.2.3 or above. | | File | go.sum |

  • Add option to ignore current goroutines

    Add option to ignore current goroutines

    This allows usage specific tests in big projects that recently started to use go-leak check.

    Signed-off-by: denis-tingajkin [email protected]

    Motivation

    https://github.com/uber-go/goleak/issues/48

  • Goleak detects leaked goroutines from other tests

    Goleak detects leaked goroutines from other tests

    Description

    We've found an interesting thing during using goleak on our CI, that goleak can detect leaked goroutine from other tests.

    Steps to reproduce

    1. Use go1.14.1 darwin/amd64
    2. Use goleak v1.0.0
    3. Run test file below goleak_test.go
    package goleak_test
    
    import (
    	"go.uber.org/goleak"
    	"testing"
    	"time"
    )
    
    func TestA(t *testing.T) {
    	go func() {
    		for {
    			<-time.After(time.Millisecond * 100)
    		}
    	}()
    }
    
    func TestB(t *testing.T) {
    	defer goleak.VerifyNone(t)
    }
    

    Expected: TestB should pass Actual: TestB fails with error "found unexpected goroutines:"

  • Using strings.HasSuffix so vendored projects can pass tests

    Using strings.HasSuffix so vendored projects can pass tests

    Vendored and non-vendored packages have different absolute paths but have the same ending.

    eg. github.com/onsi/ginkgo/internal/specrunner.(*SpecRunner).registerForInterrupts and github.com/koshatul/testproject/vendor/github.com/onsi/ginkgo/internal/specrunner.(*SpecRunner).registerForInterrupts

  • goleak is no longer compatible with Go 1.5+

    goleak is no longer compatible with Go 1.5+

    Readme explains this is compatible with Go 1.5+. However, the latest version v1.2.0 only works on Go 1.18+.

    Sample code:

    package main
    
    import (
    	"testing"
    
    	"go.uber.org/goleak"
    )
    
    func TestLeak(t *testing.T) {
    	defer goleak.VerifyNone(t)
    }
    
    $ go version
    go version go1.13.15 linux/amd64
    $ go test
    # go.uber.org/goleak
    /go/pkg/mod/go.uber.org/[email protected]/options.go:115:3: undefined: isTraceStack
    note: module requires Go 1.18
    FAIL    example.com/foo [build failed]
    

    The previous version v1.1.12 works expectedly. This seems due to https://github.com/uber-go/goleak/pull/79. Is current version only compatible with Go 1.18+?

  • Upgrade GitHub actions packages to resolve NodeJS 12 warnings

    Upgrade GitHub actions packages to resolve NodeJS 12 warnings

    Upgrades actions/checkout, actions/setup-go, and actions/cache to v3 to resolve CI warnings for NodeJS 12 deprecation.

    https://github.blog/changelog/2022-09-22-github-actions-all-actions-will-begin-running-on-node16-instead-of-node12/

    Signed-off-by: Austin Vazquez [email protected]

  • goleak finds goroutine leak in not enabled test case

    goleak finds goroutine leak in not enabled test case

    If you have a module with a leak in func leak():

    package foo
    
    import (
    	"sync"
    	"time"
    )
    
    type O struct {
    	once *sync.Once
    	quit chan struct{}
    }
    
    func NewO() *O {
    	o := &O{
    		once: &sync.Once{},
    		quit: make(chan struct{}),
    	}
    	return o
    }
    
    func (o *O) leak() {
    	go func() {
    		d := 100 * time.Millisecond
    		for {
    			select {
    			case <-o.quit:
    				return
    			case <-time.After(2 * d):
    				time.Sleep(d)
    			}
    
    		}
    
    	}()
    }
    
    func (o *O) close() {
    	o.once.Do(func() {
    		close(o.quit)
    	})
    }
    
    func (*O) run(d time.Duration) {
    	time.Sleep(d)
    }
    

    and tests checking for leaks by running defer goleak.VerifyNone(t), that don't run leak(), it will show a leak in TestC, even if the leak is in TestB without defer goleak.VerifyNone(t):

    package foo
    
    import (
    	"testing"
    	"time"
    
    	"go.uber.org/goleak"
    )
    
    func TestA(t *testing.T) {
    	defer goleak.VerifyNone(t)
    
    	o := NewO()
    	defer o.close()
    	o.run(time.Second)
    }
    
    func TestB(t *testing.T) {
    	o := NewO()
    	o.leak()
    	o.run(time.Second)
    }
    
    func TestC(t *testing.T) {
    	defer goleak.VerifyNone(t)
    
    	o := NewO()
    	defer o.close()
    	o.run(time.Second)
    }
    

    It depends on order of execution of tests.

    Here a test run:

    % go test .
    --- FAIL: TestC (1.45s)
        foo_test.go:30: found unexpected goroutines:
            [Goroutine 6 in state select, with foo.(*O).leak.func1 on top of the stack:
            goroutine 6 [select]:
            foo.(*O).leak.func1()
                    /tmp/go/goleak/foo.go:25 +0x85
            created by foo.(*O).leak
                    /tmp/go/goleak/foo.go:22 +0x56
            ]
    FAIL
    FAIL    foo     3.466s
    FAIL
    
  • Using goleak on Go benchmarks.

    Using goleak on Go benchmarks.

    It would be amazing to have goleak working on Benchmarks as well. However, I think some functions might needed to be filtered by default. Repro:

    func BenchmarkGoroutines(b *testing.B) {
    	defer goleak.VerifyNone(b)
    
    	b.ResetTimer()
    	for i := 0; i < b.N; i++ {
    		wg := sync.WaitGroup{}
    		wg.Add(2)
    
    		go func() {
    			defer wg.Done()
    		}()
    		go func() {
    			defer wg.Done()
    		}()
    
    		wg.Wait()
    	}
    }
    

    Output:

    BenchmarkGoroutines
        leaks.go:78: found unexpected goroutines:
            [Goroutine 1 in state chan receive, with testing.(*B).run1 on top of the stack:
            goroutine 1 [chan receive]:
            testing.(*B).run1(0xc00016a240)
            	/home/bwplotka/.gvm/gos/go1.18.3/src/testing/benchmark.go:235 +0xb2
            testing.(*B).Run(0xc00016a480, {0x6f69de?, 0x0?}, 0x722460)
            	/home/bwplotka/.gvm/gos/go1.18.3/src/testing/benchmark.go:676 +0x445
            testing.runBenchmarks.func1(0xc00016a480?)
            	/home/bwplotka/.gvm/gos/go1.18.3/src/testing/benchmark.go:550 +0x6e
            testing.(*B).runN(0xc00016a480, 0x1)
            	/home/bwplotka/.gvm/gos/go1.18.3/src/testing/benchmark.go:193 +0x102
            testing.runBenchmarks({0x6ffdf2, 0x28}, 0x945c20?, {0x909c80, 0x2, 0x40?})
            	/home/bwplotka/.gvm/gos/go1.18.3/src/testing/benchmark.go:559 +0x3f2
            testing.(*M).Run(0xc000132f00)
            	/home/bwplotka/.gvm/gos/go1.18.3/src/testing/testing.go:1726 +0x811
            main.main()
            	_testmain.go:57 +0x1aa
            ]
    --- FAIL: BenchmarkGoroutines
    FAIL
    
    Process finished with the exit code 1
    

    Tested on both Go version 1.18.3 and 1.19

  • Provide stub so apps using goleak can build unchanged with tinygo.

    Provide stub so apps using goleak can build unchanged with tinygo.

    Tinygo can build a large subset of go programs already. Unfortunately, tinygo currently does not quite support goleak.

    As a temporary measure, use the tinygo build tag to provide a stub for goleak. This will expand the world of go programs that run properly on tinygo, and remove one more obstacle keeping embedded system and wasm users from adopting go and goleak.

    This can be reverted if/when tinygo is enhanced to fully support goleak.

    Fixes https://github.com/uber-go/goleak/issues/71

  • Friction for tinygo users

    Friction for tinygo users

    tinygo as of release 0.22 does not support goleak; this isn't particularly surprising, as tinygo still only provides stubs for several things goleak relies upon.

    A number of apps - particularly, the one I'm trying to ship :-) - would pass tests under both go and tinygo if goleak sensed the tinygo build constraint and provided a minimal stub while tinygo matures.

    This would be an elegant way to reduce friction for goleak users who must pass tests with both go and tinygo.

    I'll provide a pull request with the simple change required. I think this is sufficient; works for my app, at least.

Related tags
:speedboat: a limited consumer goroutine or unlimited goroutine pool for easier goroutine handling and cancellation

Package pool Package pool implements a limited consumer goroutine or unlimited goroutine pool for easier goroutine handling and cancellation. Features

Jan 1, 2023
🐜🐜🐜 ants is a high-performance and low-cost goroutine pool in Go, inspired by fasthttp./ ants ζ˜―δΈ€δΈͺι«˜ζ€§θƒ½δΈ”δ½ŽζŸθ€—ηš„ goroutine 池。
🐜🐜🐜 ants is a high-performance and low-cost goroutine pool in Go, inspired by fasthttp./ ants ζ˜―δΈ€δΈͺι«˜ζ€§θƒ½δΈ”δ½ŽζŸθ€—ηš„ goroutine 池。

A goroutine pool for Go English | ???? δΈ­ζ–‡ ?? Introduction Library ants implements a goroutine pool with fixed capacity, managing and recycling a massi

Jan 2, 2023
Friends don't let friends leak secrets on their terminal window
Friends don't let friends leak secrets on their terminal window

senv - safer env Friends don't let friends leak secrets in terminal windows. ?? Print your environment to the terminal without worry.

Oct 26, 2022
Tracking down a Memory Leak in Go/SQLite

Tracking down a Memory Leak in Go/SQLite run make test - WARNING: long running - several minutes on my workstation OSs supported: Windows_NT => memory

Feb 28, 2022
A toy deadlock detector written in Go.
A toy deadlock detector written in Go.

Toy Deadlock Detector This package aims to provide a DSL to represent processes as finite state machines and their concurrent composition. A detector

Feb 2, 2022
Chronos - A static race detector for the go language
Chronos - A static race detector for the go language

Chronos Chronos is a static race detector for the Go language written in Go. Quick Start: Download the package go get -v github.com/amit-davidson/Chro

Dec 12, 2022
A faster file programming language detector
A faster file programming language detector

Programming language detector and toolbox to ignore binary or vendored files. enry, started as a port to Go of the original Linguist Ruby library, that has an improved 2x performance.

Jan 1, 2023
TProx is a fast reverse proxy path traversal detector and directory bruteforcer.
TProx is a fast reverse proxy path traversal detector and directory bruteforcer.

TProx is a fast reverse proxy path traversal detector and directory bruteforcer Install β€’ Usage β€’ Examples β€’ Join Discord Install Options From Source

Nov 9, 2022
A detector for the Trojan Source and other unicode-based vulnerabilities.

Trojan Source Detector This application detects Trojan Source attacks in source code. It can be used as part of the CI system to make sure there are n

Jan 6, 2022
A Log4J Version 2 Detector written in golang

Installation From source: go install github.com/juergenhoetzel/log4j2go/cmd/log4

Dec 20, 2021
Log4j detector and reporting server for scalable detection of vulnerable running processes.

Log4j Detector A client and reporting server to identify systems vulnerable to Log4j at scale. This work is based on Stripe's Remediation Tools, but w

Apr 8, 2022
User Agents detector for tv, phone, tablet and desktop devices.

gouseragents Accurate and fresh list of desktop, phone, tablet and tv user agents. install go get github.com/emetriq/gouseragents usage import ( "f

Apr 26, 2022
Go concurrent-safe, goroutine-safe, thread-safe queue
Go concurrent-safe, goroutine-safe, thread-safe queue

goconcurrentqueue - Concurrent safe queues The package goconcurrentqueue offers a public interface Queue with methods for a queue. It comes with multi

Dec 31, 2022
🐝 A Highly Performant and easy to use goroutine pool for Go
🐝 A Highly Performant and easy to use goroutine pool for Go

gohive Package gohive implements a simple and easy to use goroutine pool for Go Features Pool can be created with a specific size as per the requireme

Sep 26, 2022
golang worker pool , Concurrency limiting goroutine pool

golang worker pool δΈ­ζ–‡θ―΄ζ˜Ž Concurrency limiting goroutine pool. Limits the concurrency of task execution, not the number of tasks queued. Never blocks su

Dec 19, 2022
Lightweight Goroutine pool

grpool Lightweight Goroutine pool Clients can submit jobs. Dispatcher takes job, and sends it to first available worker. When worker is done with proc

Dec 6, 2022
errgroup with goroutine worker limits

neilotoole/errgroup neilotoole/errgroup is a drop-in alternative to Go's wonderful sync/errgroup but limited to N goroutines. This is useful for inter

Dec 15, 2022
Minimalistic and High-performance goroutine worker pool written in Go

pond Minimalistic and High-performance goroutine worker pool written in Go Motivation This library is meant to provide a simple way to limit concurren

Dec 22, 2022
A goroutine pool for Go
A goroutine pool for Go

Tunny is a Golang library for spawning and managing a goroutine pool, allowing you to limit work coming from any number of goroutines with a synchrono

Dec 31, 2022
Concurrency limiting goroutine pool

workerpool Concurrency limiting goroutine pool. Limits the concurrency of task execution, not the number of tasks queued. Never blocks submitting task

Dec 28, 2022