mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-17 10:20:44 +00:00
fix: filters.FilterAPI goroutine leak (#254)
## Why this should be merged This allows closing the `timeoutLoop` goroutine. Closing goroutines is the best-practice. But, more importantly, this causes the `filters.Backend` to never be GCed. Which is causing GC tests to fail in SAE. ## How this works I tried to make this as minimal of a diff as possible. ## How this was tested With this change, the SAE tests are passing: https://github.com/ava-labs/strevm/pull/64
This commit is contained in:
parent
505c2fbe72
commit
d8ff026f89
5 changed files with 90 additions and 1 deletions
|
|
@ -64,6 +64,8 @@ type FilterAPI struct {
|
||||||
filtersMu sync.Mutex
|
filtersMu sync.Mutex
|
||||||
filters map[rpc.ID]*filter
|
filters map[rpc.ID]*filter
|
||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
|
|
||||||
|
quit chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFilterAPI returns a new FilterAPI instance.
|
// NewFilterAPI returns a new FilterAPI instance.
|
||||||
|
|
@ -73,6 +75,7 @@ func NewFilterAPI(system *FilterSystem, lightMode bool) *FilterAPI {
|
||||||
events: NewEventSystem(system, lightMode),
|
events: NewEventSystem(system, lightMode),
|
||||||
filters: make(map[rpc.ID]*filter),
|
filters: make(map[rpc.ID]*filter),
|
||||||
timeout: system.cfg.Timeout,
|
timeout: system.cfg.Timeout,
|
||||||
|
quit: make(chan struct{}),
|
||||||
}
|
}
|
||||||
go api.timeoutLoop(system.cfg.Timeout)
|
go api.timeoutLoop(system.cfg.Timeout)
|
||||||
|
|
||||||
|
|
@ -86,7 +89,11 @@ func (api *FilterAPI) timeoutLoop(timeout time.Duration) {
|
||||||
ticker := time.NewTicker(timeout)
|
ticker := time.NewTicker(timeout)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
for {
|
for {
|
||||||
<-ticker.C
|
select {
|
||||||
|
case <-ticker.C:
|
||||||
|
case <-api.quit:
|
||||||
|
return
|
||||||
|
}
|
||||||
api.filtersMu.Lock()
|
api.filtersMu.Lock()
|
||||||
for id, f := range api.filters {
|
for id, f := range api.filters {
|
||||||
select {
|
select {
|
||||||
|
|
|
||||||
22
eth/filters/api.libevm.go
Normal file
22
eth/filters/api.libevm.go
Normal file
|
|
@ -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
|
||||||
|
// <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package filters
|
||||||
|
|
||||||
|
// Close releases resources held by the API.
|
||||||
|
func (api *FilterAPI) Close() {
|
||||||
|
close(api.quit)
|
||||||
|
}
|
||||||
57
eth/filters/api.libevm_test.go
Normal file
57
eth/filters/api.libevm_test.go
Normal file
|
|
@ -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
|
||||||
|
// <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
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()
|
||||||
|
}
|
||||||
1
go.mod
1
go.mod
|
|
@ -64,6 +64,7 @@ require (
|
||||||
github.com/tyler-smith/go-bip39 v1.1.0
|
github.com/tyler-smith/go-bip39 v1.1.0
|
||||||
github.com/urfave/cli/v2 v2.25.7
|
github.com/urfave/cli/v2 v2.25.7
|
||||||
go.uber.org/automaxprocs v1.5.2
|
go.uber.org/automaxprocs v1.5.2
|
||||||
|
go.uber.org/goleak v1.3.0
|
||||||
golang.org/x/crypto v0.43.0
|
golang.org/x/crypto v0.43.0
|
||||||
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa
|
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa
|
||||||
golang.org/x/mod v0.29.0
|
golang.org/x/mod v0.29.0
|
||||||
|
|
|
||||||
2
go.sum
2
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.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 h1:2LxUOGiR3O6tw8ui5sZa2LAaHnsviZdVOUZw4fvbnME=
|
||||||
go.uber.org/automaxprocs v1.5.2/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0=
|
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-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-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue