goleak
goleak copied to clipboard
Add support for regex filter
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.
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.
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.
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 CloseIdleConnections is for request client, not for server. I tried to use it, but no luck.
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 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)
}
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 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.