You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The subscription may consume the channel so that block above select.
As we checked, new NewPendingTransactionFilter calls are pending on fetching filtersMu lock.
func (sub *Subscription) Unsubscribe() {
sub.unsubOnce.Do(func() {
uninstallLoop:
for {
// write uninstall request and consume logs/hashes. This prevents
// the eventLoop broadcast method to deadlock when writing to the
// filter event channel while the subscription loop is waiting for
// this method to return (and thus not reading these events).
select {
case sub.es.uninstall <- sub.f:
break uninstallLoop
case <-sub.f.logs:
case <-sub.f.hashes:
case <-sub.f.headers:
}
}
// wait for filter to be uninstalled in work loop before returning
// this ensures that the manager won't use the event channel which
// will probably be closed by the client asap after this method returns.
<-sub.Err()
})
}
Obvious it failed to do sub.es.uninstall <- sub.f.
eventLoop is responsible for consuming the sub.es.uninstall channel.
The routine is busy doing handleTxsEvent:
It will push hashes to f.hashes channel, and now it is blocking by that channel.
func (es *EventSystem) handleTxsEvent(filters filterIndex, ev core.NewTxsEvent) {
hashes := make([]common.Hash, 0, len(ev.Txs))
for _, tx := range ev.Txs {
hashes = append(hashes, tx.Hash())
}
for _, f := range filters[PendingTransactionsSubscription] {
f.hashes <- hashes
}
}
What happened to f.hashes channel?
That is because, in the above step 3, the Unsubscribe may not consume all the hashes and break out so that step4 stucked.
The deadlock dependency is:
Routine A:NewPendingTransactionFilter want to lock filtersMu to consume hashes;
Routine B: eventLoop is waiting Routine A to consume hashes so that it can push new hash to channel.
Routine C: Unsubscribe is holding lock filtersMu, but it is waiting for Routine B to consume uninstall channel.
The text was updated successfully, but these errors were encountered:
unclezoro
changed the title
bsc dataseed sync stuck
A potential dead lock of BSC client which result in block syncing halt
Dec 30, 2020
System information
Geth version: 1.9.13
OS & Version: Linux
Expected behaviour
Client sync block normal
Actual behaviour
Client failed to sync block.
Steps to reproduce the behaviour
First change the code to make it easier to reproduce:
Do request for multi times:
Backtrace
Here is the pprof of go routine:
goroutine.txt
According to the pprof, the code is blocked on
/server/bsc/event/feed.go:170
.select
.As we checked, new
NewPendingTransactionFilter
calls are pending on fetchingfiltersMu
lock.filtersMu
lock istimeoutLoop
:The code is:
Obvious it failed to do
sub.es.uninstall <- sub.f
.eventLoop
is responsible for consuming thesub.es.uninstall
channel.The routine is busy doing
handleTxsEvent
:It will push
hashes
tof.hashes
channel, and now it is blocking by that channel.f.hashes
channel?That is because, in the above step 3, the
Unsubscribe
may not consume all thehashes
and break out so that step4 stucked.The deadlock dependency is:
Routine A:
NewPendingTransactionFilter
want to lockfiltersMu
to consumehashes
;Routine B:
eventLoop
is waiting Routine A to consumehashes
so that it can push new hash to channel.Routine C:
Unsubscribe
is holding lockfiltersMu
, but it is waiting for Routine B to consumeuninstall
channel.The text was updated successfully, but these errors were encountered: