mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-18 18:02:24 +00:00
clear address reservations inside subpools, with explanation for why it's not done at the TxPool level.
This commit is contained in:
parent
5842b1db62
commit
8d241f0475
2 changed files with 39 additions and 0 deletions
|
|
@ -1729,6 +1729,23 @@ func (p *BlobPool) Clear() {
|
||||||
log.Warn("failed to delete blob tx from backing store", "err", err)
|
log.Warn("failed to delete blob tx from backing store", "err", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// unreserve each tracked account. Ideally, we could just clear the
|
||||||
|
// reservation map in the parent txpool context. However, if we clear in
|
||||||
|
// parent context, to avoid exposing the subpool lock, we have to lock the
|
||||||
|
// reservations and then lock each subpool.
|
||||||
|
//
|
||||||
|
// This creates the potential for a deadlock situation:
|
||||||
|
//
|
||||||
|
// * TxPool.Clear locks the reservations
|
||||||
|
// * a new transaction is received which locks the subpool mutex
|
||||||
|
// * TxPool.Clear attempts to lock subpool mutex
|
||||||
|
//
|
||||||
|
// The transaction addition may attempt to reserve the sender addr which
|
||||||
|
// can't happen until Clear releases the reservation lock. Clear cannot
|
||||||
|
// acquire the subpool lock until the transaction addition is completed.
|
||||||
|
for acct, _ := range p.index {
|
||||||
|
p.reserve(acct, false)
|
||||||
|
}
|
||||||
p.lookup = make(map[common.Hash]uint64)
|
p.lookup = make(map[common.Hash]uint64)
|
||||||
p.index = make(map[common.Address][]*blobTxMeta)
|
p.index = make(map[common.Address][]*blobTxMeta)
|
||||||
p.spent = make(map[common.Address]*uint256.Int)
|
p.spent = make(map[common.Address]*uint256.Int)
|
||||||
|
|
|
||||||
|
|
@ -1968,6 +1968,28 @@ func (p *LegacyPool) Clear() {
|
||||||
p.mu.Lock()
|
p.mu.Lock()
|
||||||
defer p.mu.Unlock()
|
defer p.mu.Unlock()
|
||||||
|
|
||||||
|
// unreserve each tracked account. Ideally, we could just clear the
|
||||||
|
// reservation map in the parent txpool context. However, if we clear in
|
||||||
|
// parent context, to avoid exposing the subpool lock, we have to lock the
|
||||||
|
// reservations and then lock each subpool.
|
||||||
|
//
|
||||||
|
// This creates the potential for a deadlock situation:
|
||||||
|
//
|
||||||
|
// * TxPool.Clear locks the reservations
|
||||||
|
// * a new transaction is received which locks the subpool mutex
|
||||||
|
// * TxPool.Clear attempts to lock subpool mutex
|
||||||
|
//
|
||||||
|
// The transaction addition may attempt to reserve the sender addr which
|
||||||
|
// can't happen until Clear releases the reservation lock. Clear cannot
|
||||||
|
// acquire the subpool lock until the transaction addition is completed.
|
||||||
|
for _, tx := range p.all.remotes {
|
||||||
|
senderAddr, _ := types.Sender(p.signer, tx)
|
||||||
|
p.reserve(senderAddr, false)
|
||||||
|
}
|
||||||
|
for localSender, _ := range p.locals.accounts {
|
||||||
|
p.reserve(localSender, false)
|
||||||
|
}
|
||||||
|
|
||||||
p.all = newLookup()
|
p.all = newLookup()
|
||||||
p.priced = newPricedList(p.all)
|
p.priced = newPricedList(p.all)
|
||||||
p.pending = make(map[common.Address]*list)
|
p.pending = make(map[common.Address]*list)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue