Open 9iang22 opened 2 years ago
Could repro, looks like the following diff kinda fixes it. Maybe we should add a timeout to the rpc server/rpc client context.
diff --git a/rpc/handler.go b/rpc/handler.go
index f3052e7eb..f921e30ac 100644
--- a/rpc/handler.go
+++ b/rpc/handler.go
@@ -219,7 +219,7 @@ func (h *handler) cancelServerSubscriptions(err error) {
func (h *handler) startCallProc(fn func(*callProc)) {
h.callWG.Add(1)
go func() {
- ctx, cancel := context.WithCancel(h.rootCtx)
+ ctx, cancel := context.WithTimeout(h.rootCtx, time.Second)
defer h.callWG.Done()
defer cancel()
fn(&callProc{ctx: ctx})
*Edit To be clear I'm not proposing this as a fix, it should only show where the issue is
i try to test it but i need to know "goleak" in which branch
i try to test it but i need to know "goleak" in which branch
It's a third party leak checker, include by go.uber.org/goleak
http is also leaking.
func TestHTTPClientGoroutineLeak(t *testing.T) {
defer goleak.VerifyNone(t)
ctx := context.Background()
// connect to local node
client, err := DialContext(ctx, "http://localhost:8545")
if err != nil {
t.Fatal("can't dial", err)
}
defer client.Close()
if err := client.CallContext(ctx, nil, "eth_chainId"); err != nil {
t.Fatal(err)
}
}
// Once run above test, go routine leak detected.
--- FAIL: TestHTTPClientGoroutineLeak (0.45s)
/Users/tak/Documents/angoya/_sandbox/go-ethereum/rpc/client_test.go:70: found unexpected goroutines:
[Goroutine 25 in state IO wait, with internal/poll.runtime_pollWait on top of the stack:
...
Then I noticed that missing to close idling connections
diff --git a/rpc/http.go b/rpc/http.go
index bbabe15ba..4f45d8d46 100644
--- a/rpc/http.go
+++ b/rpc/http.go
@@ -73,6 +73,7 @@ func (hc *httpConn) readBatch() ([]*jsonrpcMessage, bool, error) {
func (hc *httpConn) close() {
hc.closeOnce.Do(func() { close(hc.closeCh) })
+ hc.client.CloseIdleConnections()
}
And missing httpConn.close()
diff --git a/rpc/client.go b/rpc/client.go
index a509cb2e0..e508ed304 100644
--- a/rpc/client.go
+++ b/rpc/client.go
@@ -280,6 +280,7 @@ func (c *Client) SupportedModules() (map[string]string, error) {
// Close closes the client, aborting any in-flight requests.
func (c *Client) Close() {
if c.isHTTP {
+ c.writeConn.(*httpConn).close()
return
}
Those two changes solve go routine leak.
Added help wanted labels. Would be nice if someone could verify that this is still and issue and propose some PRs to fix it
System information
OS & Version: Windows 11 & Ubuntu 18.04 Commit hash : develop
When I run the TestClientCancelWebsocket with goleak, there are some go routine leaks, as mentioned below. Actually I think it blocks at this function.
In
TestClientCancelWebsocket
, thefn
is to test block (test_block
) so I think it may block forever and theh.callWG.Done
will never be called. Although it is caused by a client test, it causes leaks in the server part. I wonder if it is normal for thisfn
call without a timeout.Expected behaviour
Pass
Actual behaviour
Steps to reproduce the behaviour
run TestClientCancelWebsocket with goleak
Backtrace