@@ -489,7 +489,7 @@ class PeerManagerImpl final : public PeerManager
489
489
CTxMemPool& pool, node::Warnings& warnings, Options opts);
490
490
491
491
/* * Overridden from CValidationInterface. */
492
- void ActiveTipChange (const CBlockIndex* new_tip, bool ) override
492
+ void ActiveTipChange (const CBlockIndex& new_tip, bool ) override
493
493
EXCLUSIVE_LOCKS_REQUIRED(!m_tx_download_mutex);
494
494
void BlockConnected (ChainstateRole role, const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexConnected) override
495
495
EXCLUSIVE_LOCKS_REQUIRED(!m_tx_download_mutex);
@@ -780,10 +780,8 @@ class PeerManagerImpl final : public PeerManager
780
780
* - A txhash (txid or wtxid) in m_txrequest is not also in m_recent_rejects_reconsiderable.
781
781
* - A txhash (txid or wtxid) in m_txrequest is not also in m_recent_confirmed_transactions.
782
782
* - Each data structure's limits hold (m_orphanage max size, m_txrequest per-peer limits, etc).
783
- *
784
- * m_tx_download_mutex must be acquired before mempool.cs
785
783
*/
786
- Mutex m_tx_download_mutex;
784
+ Mutex m_tx_download_mutex ACQUIRED_BEFORE (m_mempool.cs) ;
787
785
TxRequestTracker m_txrequest GUARDED_BY (m_tx_download_mutex);
788
786
std::unique_ptr<TxReconciliationTracker> m_txreconciliation;
789
787
@@ -2070,8 +2068,10 @@ void PeerManagerImpl::StartScheduledTasks(CScheduler& scheduler)
2070
2068
scheduler.scheduleFromNow ([&] { ReattemptInitialBroadcast (scheduler); }, delta);
2071
2069
}
2072
2070
2073
- void PeerManagerImpl::ActiveTipChange (const CBlockIndex* new_tip, bool is_ibd)
2071
+ void PeerManagerImpl::ActiveTipChange (const CBlockIndex& new_tip, bool is_ibd)
2074
2072
{
2073
+ // Ensure mempool mutex was released, otherwise deadlock may occur if another thread holding
2074
+ // m_tx_download_mutex waits on the mempool mutex.
2075
2075
AssertLockNotHeld (m_mempool.cs );
2076
2076
AssertLockNotHeld (m_tx_download_mutex);
2077
2077
@@ -2123,8 +2123,6 @@ void PeerManagerImpl::BlockConnected(
2123
2123
if (ptx->HasWitness ()) {
2124
2124
m_recent_confirmed_transactions.insert (ptx->GetWitnessHash ().ToUint256 ());
2125
2125
}
2126
- }
2127
- for (const auto & ptx : pblock->vtx ) {
2128
2126
m_txrequest.ForgetTxHash (ptx->GetHash ());
2129
2127
m_txrequest.ForgetTxHash (ptx->GetWitnessHash ());
2130
2128
}
@@ -5336,6 +5334,7 @@ bool PeerManagerImpl::MaybeDiscourageAndDisconnect(CNode& pnode, Peer& peer)
5336
5334
5337
5335
bool PeerManagerImpl::ProcessMessages (CNode* pfrom, std::atomic<bool >& interruptMsgProc)
5338
5336
{
5337
+ AssertLockNotHeld (m_tx_download_mutex);
5339
5338
AssertLockHeld (g_msgproc_mutex);
5340
5339
5341
5340
PeerRef peer = GetPeerRef (pfrom->GetId ());
@@ -5827,6 +5826,7 @@ bool PeerManagerImpl::SetupAddressRelay(const CNode& node, Peer& peer)
5827
5826
5828
5827
bool PeerManagerImpl::SendMessages (CNode* pto)
5829
5828
{
5829
+ AssertLockNotHeld (m_tx_download_mutex);
5830
5830
AssertLockHeld (g_msgproc_mutex);
5831
5831
5832
5832
PeerRef peer = GetPeerRef (pto->GetId ());
@@ -6297,32 +6297,33 @@ bool PeerManagerImpl::SendMessages(CNode* pto)
6297
6297
//
6298
6298
// Message: getdata (transactions)
6299
6299
//
6300
- LOCK (m_tx_download_mutex);
6301
- std::vector<std::pair<NodeId, GenTxid>> expired;
6302
- auto requestable = m_txrequest.GetRequestable (pto->GetId (), current_time, &expired);
6303
- for (const auto & entry : expired) {
6304
- LogPrint (BCLog::NET, " timeout of inflight %s %s from peer=%d\n " , entry.second .IsWtxid () ? " wtx" : " tx" ,
6305
- entry.second .GetHash ().ToString (), entry.first );
6306
- }
6307
- for (const GenTxid& gtxid : requestable) {
6308
- // Exclude m_recent_rejects_reconsiderable: we may be requesting a missing parent
6309
- // that was previously rejected for being too low feerate.
6310
- if (!AlreadyHaveTx (gtxid, /* include_reconsiderable=*/ false )) {
6311
- LogPrint (BCLog::NET, " Requesting %s %s peer=%d\n " , gtxid.IsWtxid () ? " wtx" : " tx" ,
6312
- gtxid.GetHash ().ToString (), pto->GetId ());
6313
- vGetData.emplace_back (gtxid.IsWtxid () ? MSG_WTX : (MSG_TX | GetFetchFlags (*peer)), gtxid.GetHash ());
6314
- if (vGetData.size () >= MAX_GETDATA_SZ) {
6315
- MakeAndPushMessage (*pto, NetMsgType::GETDATA, vGetData);
6316
- vGetData.clear ();
6300
+ {
6301
+ LOCK (m_tx_download_mutex);
6302
+ std::vector<std::pair<NodeId, GenTxid>> expired;
6303
+ auto requestable = m_txrequest.GetRequestable (pto->GetId (), current_time, &expired);
6304
+ for (const auto & entry : expired) {
6305
+ LogPrint (BCLog::NET, " timeout of inflight %s %s from peer=%d\n " , entry.second .IsWtxid () ? " wtx" : " tx" ,
6306
+ entry.second .GetHash ().ToString (), entry.first );
6307
+ }
6308
+ for (const GenTxid& gtxid : requestable) {
6309
+ // Exclude m_recent_rejects_reconsiderable: we may be requesting a missing parent
6310
+ // that was previously rejected for being too low feerate.
6311
+ if (!AlreadyHaveTx (gtxid, /* include_reconsiderable=*/ false )) {
6312
+ LogPrint (BCLog::NET, " Requesting %s %s peer=%d\n " , gtxid.IsWtxid () ? " wtx" : " tx" ,
6313
+ gtxid.GetHash ().ToString (), pto->GetId ());
6314
+ vGetData.emplace_back (gtxid.IsWtxid () ? MSG_WTX : (MSG_TX | GetFetchFlags (*peer)), gtxid.GetHash ());
6315
+ if (vGetData.size () >= MAX_GETDATA_SZ) {
6316
+ MakeAndPushMessage (*pto, NetMsgType::GETDATA, vGetData);
6317
+ vGetData.clear ();
6318
+ }
6319
+ m_txrequest.RequestedTx (pto->GetId (), gtxid.GetHash (), current_time + GETDATA_TX_INTERVAL);
6320
+ } else {
6321
+ // We have already seen this transaction, no need to download. This is just a belt-and-suspenders, as
6322
+ // this should already be called whenever a transaction becomes AlreadyHaveTx().
6323
+ m_txrequest.ForgetTxHash (gtxid.GetHash ());
6317
6324
}
6318
- m_txrequest.RequestedTx (pto->GetId (), gtxid.GetHash (), current_time + GETDATA_TX_INTERVAL);
6319
- } else {
6320
- // We have already seen this transaction, no need to download. This is just a belt-and-suspenders, as
6321
- // this should already be called whenever a transaction becomes AlreadyHaveTx().
6322
- m_txrequest.ForgetTxHash (gtxid.GetHash ());
6323
6325
}
6324
- }
6325
-
6326
+ } // release m_tx_download_mutex
6326
6327
6327
6328
if (!vGetData.empty ())
6328
6329
MakeAndPushMessage (*pto, NetMsgType::GETDATA, vGetData);
0 commit comments