goleak icon indicating copy to clipboard operation
goleak copied to clipboard

Add support for regex filter

Open rleungx opened this issue 5 years ago • 8 comments

Considering that we may depend on some other repositories, but we don't care too much about those repos. An alternative would be to support regex filter.

rleungx avatar Sep 23 '19 03:09 rleungx

Substring and regex filters seem OK, but it might be better to start with an explicit "IgnorePackage".

Putting more generic skips makes it easier to accidentally ignore real leaks as well, so want to make it more specific to the type of leak being ignored.

prashantv avatar Sep 30 '19 03:09 prashantv

This is critical if a project uses HTTP keep-alive in tests. It's designed to be leaking, even we use SetKeepAlivesEnabled(false) the idle connection will keep 2 goroutines to keep checking.

Currently, we have to do something like this to get around it:


	goleak.VerifyTestMain(
		m,
		goleak.IgnoreTopFunction("internal/poll.runtime_pollWait"),
		goleak.IgnoreTopFunction("net/http.(*persistConn).writeLoop"),
		goleak.IgnoreTopFunction("net/http.(*persistConn).readLoop"),
	)

I feel it will accidentally hide other leaks.

ysmood avatar Aug 29 '20 01:08 ysmood

Is the server under control of the test? If so, closing the server will also close any keep-alive connections, and should avoid leaks. If the server is not under control of the test, but the client is, then the CloseIdleConnections methods can be used to close the idle connections: https://golang.org/pkg/net/http/#Client.CloseIdleConnections https://golang.org/pkg/net/http/#Transport.CloseIdleConnections

I would highly recommend closing all connections as part of your test cleaning up any created resources, as there definitely can be real leaks missed by ignoring all HTTP read/write goroutines.

prashantv avatar Sep 02 '20 05:09 prashantv

@prashantv CloseIdleConnections is for request client, not for server. I tried to use it, but no luck.

ysmood avatar Sep 02 '20 07:09 ysmood

On the server side, closing the server will close idle connections, see documentation: https://golang.org/pkg/net/http/#Server.Close https://golang.org/pkg/net/http/#Server.Shutdown

prashantv avatar Sep 02 '20 15:09 prashantv

@prashantv Thank you! It's my fault. The actual leaking part is the HTTP client, not the server. The code below will leak:

package main_test

import (
	"net"
	"net/http"
	"testing"

	"go.uber.org/goleak"
)

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

func Test(t *testing.T) {
	mux := http.NewServeMux()
	srv := &http.Server{Handler: mux}

	l, _ := net.Listen("tcp", "127.0.0.1:0")
	defer l.Close()

	go srv.Serve(l)
	defer srv.Close()

	mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("ok"))
	})

	r, _ := http.NewRequest(http.MethodGet, "http://"+l.Addr().String(), nil)

	(&http.Client{
		Transport: &http.Transport{
			DisableKeepAlives: true,
		},
	}).Do(r)
}

ysmood avatar Sep 03 '20 00:09 ysmood

That code actually has a leak -- it's not closing the response body. The leak is not an idle connection, but an active connection for a request that hasn't completed, because the response body has not been read and closed. Add a resp.Body.Close() and the leak will go away.

prashantv avatar Sep 03 '20 04:09 prashantv

@prashantv Thank you! It's my fault. The actual leaking part is the HTTP client, not the server.

I mean I have already solved the leak. Not only Body.Close(), read the body ioutil.ReadAll(res.Body) will also release the resource. Also if we remove the w.Write([]byte("ok")), the leak will also go away. As long as we know which part goes wrong we can solve it easily.

Sorry for the noise I made, the problem is not related to goleak at all. It's my misuse.

ysmood avatar Sep 03 '20 04:09 ysmood