mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-23 13:16:42 +00:00
fix: discovery AyncFilter deadlock on shutdown (#3347)
This commit is contained in:
parent
5cc443609f
commit
bfa5f14826
1 changed files with 9 additions and 4 deletions
|
|
@ -178,7 +178,7 @@ type AsyncFilterFunc func(context.Context, *Node) *Node
|
||||||
func AsyncFilter(it Iterator, check AsyncFilterFunc, workers int) Iterator {
|
func AsyncFilter(it Iterator, check AsyncFilterFunc, workers int) Iterator {
|
||||||
f := &asyncFilterIter{
|
f := &asyncFilterIter{
|
||||||
it: ensureSourceIter(it),
|
it: ensureSourceIter(it),
|
||||||
slots: make(chan struct{}, workers+1),
|
slots: make(chan struct{}, workers+1), // extra 1 slot to make sure all the goroutines can be completed
|
||||||
passed: make(chan iteratorItem),
|
passed: make(chan iteratorItem),
|
||||||
}
|
}
|
||||||
for range cap(f.slots) {
|
for range cap(f.slots) {
|
||||||
|
|
@ -193,6 +193,9 @@ func AsyncFilter(it Iterator, check AsyncFilterFunc, workers int) Iterator {
|
||||||
return
|
return
|
||||||
case <-f.slots:
|
case <-f.slots:
|
||||||
}
|
}
|
||||||
|
defer func() {
|
||||||
|
f.slots <- struct{}{} // the iterator has ended
|
||||||
|
}()
|
||||||
// read from the iterator and start checking nodes in parallel
|
// read from the iterator and start checking nodes in parallel
|
||||||
// when a node is checked, it will be sent to the passed channel
|
// when a node is checked, it will be sent to the passed channel
|
||||||
// and the slot will be released
|
// and the slot will be released
|
||||||
|
|
@ -201,7 +204,11 @@ func AsyncFilter(it Iterator, check AsyncFilterFunc, workers int) Iterator {
|
||||||
nodeSource := f.it.NodeSource()
|
nodeSource := f.it.NodeSource()
|
||||||
|
|
||||||
// check the node async, in a separate goroutine
|
// check the node async, in a separate goroutine
|
||||||
<-f.slots
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
case <-f.slots:
|
||||||
|
}
|
||||||
go func() {
|
go func() {
|
||||||
if nn := check(ctx, node); nn != nil {
|
if nn := check(ctx, node); nn != nil {
|
||||||
item := iteratorItem{nn, nodeSource}
|
item := iteratorItem{nn, nodeSource}
|
||||||
|
|
@ -213,8 +220,6 @@ func AsyncFilter(it Iterator, check AsyncFilterFunc, workers int) Iterator {
|
||||||
f.slots <- struct{}{}
|
f.slots <- struct{}{}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
// the iterator has ended
|
|
||||||
f.slots <- struct{}{}
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return f
|
return f
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue