mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-20 13:44:31 +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
|
||||
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 {
|
||||
|
|
|
|||
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/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
|
||||
|
|
|
|||
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.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=
|
||||
|
|
|
|||
Loading…
Reference in a new issue