mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-06 14:19:59 -05:00
Close minor startup race between main and scheduler threads
Don't schedule class PeerManagerImpl's background tasks from its constructor, but instead do that from a separate method, StartScheduledTasks(), that can be called later at the end of startup, after other things, such as the active chain, are initialzed.
This commit is contained in:
parent
4b1fb50def
commit
703b1e612a
5 changed files with 21 additions and 11 deletions
|
@ -1180,7 +1180,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||||
|
|
||||||
assert(!node.peerman);
|
assert(!node.peerman);
|
||||||
node.peerman = PeerManager::make(chainparams, *node.connman, *node.addrman, node.banman.get(),
|
node.peerman = PeerManager::make(chainparams, *node.connman, *node.addrman, node.banman.get(),
|
||||||
*node.scheduler, chainman, *node.mempool, ignores_incoming_txs);
|
chainman, *node.mempool, ignores_incoming_txs);
|
||||||
RegisterValidationInterface(node.peerman.get());
|
RegisterValidationInterface(node.peerman.get());
|
||||||
|
|
||||||
// sanitize comments per BIP-0014, format user agent and check total size
|
// sanitize comments per BIP-0014, format user agent and check total size
|
||||||
|
@ -1789,6 +1789,8 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||||
banman->DumpBanlist();
|
banman->DumpBanlist();
|
||||||
}, DUMP_BANS_INTERVAL);
|
}, DUMP_BANS_INTERVAL);
|
||||||
|
|
||||||
|
if (node.peerman) node.peerman->StartScheduledTasks(*node.scheduler);
|
||||||
|
|
||||||
#if HAVE_SYSTEM
|
#if HAVE_SYSTEM
|
||||||
StartupNotify(args);
|
StartupNotify(args);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -271,7 +271,7 @@ class PeerManagerImpl final : public PeerManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PeerManagerImpl(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman,
|
PeerManagerImpl(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman,
|
||||||
BanMan* banman, CScheduler& scheduler, ChainstateManager& chainman,
|
BanMan* banman, ChainstateManager& chainman,
|
||||||
CTxMemPool& pool, bool ignore_incoming_txs);
|
CTxMemPool& pool, bool ignore_incoming_txs);
|
||||||
|
|
||||||
/** Overridden from CValidationInterface. */
|
/** Overridden from CValidationInterface. */
|
||||||
|
@ -288,6 +288,7 @@ public:
|
||||||
bool SendMessages(CNode* pto) override EXCLUSIVE_LOCKS_REQUIRED(pto->cs_sendProcessing);
|
bool SendMessages(CNode* pto) override EXCLUSIVE_LOCKS_REQUIRED(pto->cs_sendProcessing);
|
||||||
|
|
||||||
/** Implement PeerManager */
|
/** Implement PeerManager */
|
||||||
|
void StartScheduledTasks(CScheduler& scheduler) override;
|
||||||
void CheckForStaleTipAndEvictPeers() override;
|
void CheckForStaleTipAndEvictPeers() override;
|
||||||
bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) const override;
|
bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) const override;
|
||||||
bool IgnoresIncomingTxs() override { return m_ignore_incoming_txs; }
|
bool IgnoresIncomingTxs() override { return m_ignore_incoming_txs; }
|
||||||
|
@ -1396,14 +1397,14 @@ bool PeerManagerImpl::BlockRequestAllowed(const CBlockIndex* pindex)
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<PeerManager> PeerManager::make(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman,
|
std::unique_ptr<PeerManager> PeerManager::make(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman,
|
||||||
BanMan* banman, CScheduler& scheduler, ChainstateManager& chainman,
|
BanMan* banman, ChainstateManager& chainman,
|
||||||
CTxMemPool& pool, bool ignore_incoming_txs)
|
CTxMemPool& pool, bool ignore_incoming_txs)
|
||||||
{
|
{
|
||||||
return std::make_unique<PeerManagerImpl>(chainparams, connman, addrman, banman, scheduler, chainman, pool, ignore_incoming_txs);
|
return std::make_unique<PeerManagerImpl>(chainparams, connman, addrman, banman, chainman, pool, ignore_incoming_txs);
|
||||||
}
|
}
|
||||||
|
|
||||||
PeerManagerImpl::PeerManagerImpl(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman,
|
PeerManagerImpl::PeerManagerImpl(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman,
|
||||||
BanMan* banman, CScheduler& scheduler, ChainstateManager& chainman,
|
BanMan* banman, ChainstateManager& chainman,
|
||||||
CTxMemPool& pool, bool ignore_incoming_txs)
|
CTxMemPool& pool, bool ignore_incoming_txs)
|
||||||
: m_chainparams(chainparams),
|
: m_chainparams(chainparams),
|
||||||
m_connman(connman),
|
m_connman(connman),
|
||||||
|
@ -1412,6 +1413,10 @@ PeerManagerImpl::PeerManagerImpl(const CChainParams& chainparams, CConnman& conn
|
||||||
m_chainman(chainman),
|
m_chainman(chainman),
|
||||||
m_mempool(pool),
|
m_mempool(pool),
|
||||||
m_ignore_incoming_txs(ignore_incoming_txs)
|
m_ignore_incoming_txs(ignore_incoming_txs)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PeerManagerImpl::StartScheduledTasks(CScheduler& scheduler)
|
||||||
{
|
{
|
||||||
// Stale tip checking and peer eviction are on two different timers, but we
|
// Stale tip checking and peer eviction are on two different timers, but we
|
||||||
// don't want them to get out of sync due to drift in the scheduler, so we
|
// don't want them to get out of sync due to drift in the scheduler, so we
|
||||||
|
|
|
@ -37,10 +37,13 @@ class PeerManager : public CValidationInterface, public NetEventsInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static std::unique_ptr<PeerManager> make(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman,
|
static std::unique_ptr<PeerManager> make(const CChainParams& chainparams, CConnman& connman, CAddrMan& addrman,
|
||||||
BanMan* banman, CScheduler& scheduler, ChainstateManager& chainman,
|
BanMan* banman, ChainstateManager& chainman,
|
||||||
CTxMemPool& pool, bool ignore_incoming_txs);
|
CTxMemPool& pool, bool ignore_incoming_txs);
|
||||||
virtual ~PeerManager() { }
|
virtual ~PeerManager() { }
|
||||||
|
|
||||||
|
/** Begin running background tasks, should only be called once */
|
||||||
|
virtual void StartScheduledTasks(CScheduler& scheduler) = 0;
|
||||||
|
|
||||||
/** Get statistics from node state */
|
/** Get statistics from node state */
|
||||||
virtual bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) const = 0;
|
virtual bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) const = 0;
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ BOOST_AUTO_TEST_CASE(outbound_slow_chain_eviction)
|
||||||
const CChainParams& chainparams = Params();
|
const CChainParams& chainparams = Params();
|
||||||
auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman);
|
auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman);
|
||||||
auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, nullptr,
|
auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, nullptr,
|
||||||
*m_node.scheduler, *m_node.chainman, *m_node.mempool, false);
|
*m_node.chainman, *m_node.mempool, false);
|
||||||
|
|
||||||
// Mock an outbound peer
|
// Mock an outbound peer
|
||||||
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
|
CAddress addr1(ip(0xa0b0c001), NODE_NONE);
|
||||||
|
@ -121,7 +121,7 @@ BOOST_AUTO_TEST_CASE(stale_tip_peer_management)
|
||||||
const CChainParams& chainparams = Params();
|
const CChainParams& chainparams = Params();
|
||||||
auto connman = std::make_unique<ConnmanTestMsg>(0x1337, 0x1337, *m_node.addrman);
|
auto connman = std::make_unique<ConnmanTestMsg>(0x1337, 0x1337, *m_node.addrman);
|
||||||
auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, nullptr,
|
auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, nullptr,
|
||||||
*m_node.scheduler, *m_node.chainman, *m_node.mempool, false);
|
*m_node.chainman, *m_node.mempool, false);
|
||||||
|
|
||||||
constexpr int max_outbound_full_relay = MAX_OUTBOUND_FULL_RELAY_CONNECTIONS;
|
constexpr int max_outbound_full_relay = MAX_OUTBOUND_FULL_RELAY_CONNECTIONS;
|
||||||
CConnman::Options options;
|
CConnman::Options options;
|
||||||
|
@ -194,7 +194,7 @@ BOOST_AUTO_TEST_CASE(peer_discouragement)
|
||||||
auto banman = std::make_unique<BanMan>(m_args.GetDataDirBase() / "banlist", nullptr, DEFAULT_MISBEHAVING_BANTIME);
|
auto banman = std::make_unique<BanMan>(m_args.GetDataDirBase() / "banlist", nullptr, DEFAULT_MISBEHAVING_BANTIME);
|
||||||
auto connman = std::make_unique<ConnmanTestMsg>(0x1337, 0x1337, *m_node.addrman);
|
auto connman = std::make_unique<ConnmanTestMsg>(0x1337, 0x1337, *m_node.addrman);
|
||||||
auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, banman.get(),
|
auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, banman.get(),
|
||||||
*m_node.scheduler, *m_node.chainman, *m_node.mempool, false);
|
*m_node.chainman, *m_node.mempool, false);
|
||||||
|
|
||||||
CNetAddr tor_netaddr;
|
CNetAddr tor_netaddr;
|
||||||
BOOST_REQUIRE(
|
BOOST_REQUIRE(
|
||||||
|
@ -288,7 +288,7 @@ BOOST_AUTO_TEST_CASE(DoS_bantime)
|
||||||
auto banman = std::make_unique<BanMan>(m_args.GetDataDirBase() / "banlist", nullptr, DEFAULT_MISBEHAVING_BANTIME);
|
auto banman = std::make_unique<BanMan>(m_args.GetDataDirBase() / "banlist", nullptr, DEFAULT_MISBEHAVING_BANTIME);
|
||||||
auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman);
|
auto connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman);
|
||||||
auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, banman.get(),
|
auto peerLogic = PeerManager::make(chainparams, *connman, *m_node.addrman, banman.get(),
|
||||||
*m_node.scheduler, *m_node.chainman, *m_node.mempool, false);
|
*m_node.chainman, *m_node.mempool, false);
|
||||||
|
|
||||||
banman->ClearBanned();
|
banman->ClearBanned();
|
||||||
int64_t nStartTime = GetTime();
|
int64_t nStartTime = GetTime();
|
||||||
|
|
|
@ -197,7 +197,7 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const
|
||||||
m_node.banman = std::make_unique<BanMan>(m_args.GetDataDirBase() / "banlist", nullptr, DEFAULT_MISBEHAVING_BANTIME);
|
m_node.banman = std::make_unique<BanMan>(m_args.GetDataDirBase() / "banlist", nullptr, DEFAULT_MISBEHAVING_BANTIME);
|
||||||
m_node.connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman); // Deterministic randomness for tests.
|
m_node.connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman); // Deterministic randomness for tests.
|
||||||
m_node.peerman = PeerManager::make(chainparams, *m_node.connman, *m_node.addrman,
|
m_node.peerman = PeerManager::make(chainparams, *m_node.connman, *m_node.addrman,
|
||||||
m_node.banman.get(), *m_node.scheduler, *m_node.chainman,
|
m_node.banman.get(), *m_node.chainman,
|
||||||
*m_node.mempool, false);
|
*m_node.mempool, false);
|
||||||
{
|
{
|
||||||
CConnman::Options options;
|
CConnman::Options options;
|
||||||
|
|
Loading…
Add table
Reference in a new issue