diff --git a/eth/filters/api.go b/eth/filters/api.go index 41e15e0ddc..93071111a6 100644 --- a/eth/filters/api.go +++ b/eth/filters/api.go @@ -64,6 +64,8 @@ type FilterAPI struct { filtersMu sync.Mutex filters map[rpc.ID]*filter timeout time.Duration + + quit chan struct{} } // NewFilterAPI returns a new FilterAPI instance. @@ -73,6 +75,7 @@ func NewFilterAPI(system *FilterSystem, lightMode bool) *FilterAPI { events: NewEventSystem(system, lightMode), filters: make(map[rpc.ID]*filter), timeout: system.cfg.Timeout, + quit: make(chan struct{}), } go api.timeoutLoop(system.cfg.Timeout) @@ -86,7 +89,11 @@ func (api *FilterAPI) timeoutLoop(timeout time.Duration) { ticker := time.NewTicker(timeout) defer ticker.Stop() for { - <-ticker.C + select { + case <-ticker.C: + case <-api.quit: + return + } api.filtersMu.Lock() for id, f := range api.filters { select { diff --git a/eth/filters/api.libevm.go b/eth/filters/api.libevm.go new file mode 100644 index 0000000000..dff4f52ea6 --- /dev/null +++ b/eth/filters/api.libevm.go @@ -0,0 +1,22 @@ +// Copyright 2026 the libevm authors. +// +// The libevm additions to go-ethereum are free software: you can redistribute +// them and/or modify them under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, +// or (at your option) any later version. +// +// The libevm additions are distributed in the hope that they will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser +// General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see +// . + +package filters + +// Close releases resources held by the API. +func (api *FilterAPI) Close() { + close(api.quit) +} diff --git a/eth/filters/api.libevm_test.go b/eth/filters/api.libevm_test.go new file mode 100644 index 0000000000..c18134ac01 --- /dev/null +++ b/eth/filters/api.libevm_test.go @@ -0,0 +1,57 @@ +// Copyright 2026 the libevm authors. +// +// The libevm additions to go-ethereum are free software: you can redistribute +// them and/or modify them under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, either version 3 of the License, +// or (at your option) any later version. +// +// The libevm additions are distributed in the hope that they will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser +// General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see +// . + +package filters + +import ( + "testing" + + "go.uber.org/goleak" + + "github.com/ava-labs/libevm/core" + "github.com/ava-labs/libevm/core/rawdb" + "github.com/ava-labs/libevm/event" +) + +// A closeableTestBackend tracks all subscriptions that it produces, allowing +// them to be cleaned up to avoid the leak of [EventSystem.eventLoop]. +type closeableTestBackend struct { + testBackend + subs event.SubscriptionScope +} + +func (b *closeableTestBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.Subscription { + sub := b.testBackend.SubscribeNewTxsEvent(ch) + return b.subs.Track(sub) +} + +func (b *closeableTestBackend) Close() { + b.subs.Close() +} + +func TestClose(t *testing.T) { + defer goleak.VerifyNone(t, goleak.IgnoreCurrent()) + + backend := &closeableTestBackend{ + testBackend: testBackend{ + db: rawdb.NewMemoryDatabase(), + }, + } + defer backend.Close() + sys := NewFilterSystem(backend, Config{}) + api := NewFilterAPI(sys, false) + api.Close() +} diff --git a/go.mod b/go.mod index f966a6849f..0ae1145599 100644 --- a/go.mod +++ b/go.mod @@ -64,6 +64,7 @@ require ( github.com/tyler-smith/go-bip39 v1.1.0 github.com/urfave/cli/v2 v2.25.7 go.uber.org/automaxprocs v1.5.2 + go.uber.org/goleak v1.3.0 golang.org/x/crypto v0.43.0 golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa golang.org/x/mod v0.29.0 diff --git a/go.sum b/go.sum index 53786439a4..3f876903d9 100644 --- a/go.sum +++ b/go.sum @@ -622,6 +622,8 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/automaxprocs v1.5.2 h1:2LxUOGiR3O6tw8ui5sZa2LAaHnsviZdVOUZw4fvbnME= go.uber.org/automaxprocs v1.5.2/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=