Skip to content

Commit b93b9d5

Browse files
committed
Simplify and fix notifier removal on error.
This factors out the common logic to run over all ZMQ notifiers, call a function on them, and remove them from the list if the function fails is extracted to a helper method. Note that this also fixes a potential memory leak: When a notifier was removed previously after its callback returned false, it would just be removed from the list without destructing the object. This is now done correctly by std::unique_ptr behind the scenes.
1 parent e15b1cf commit b93b9d5

File tree

1 file changed

+24
-26
lines changed

1 file changed

+24
-26
lines changed

src/zmq/zmqnotificationinterface.cpp

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -114,45 +114,43 @@ void CZMQNotificationInterface::Shutdown()
114114
}
115115
}
116116

117-
void CZMQNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
118-
{
119-
if (fInitialDownload || pindexNew == pindexFork) // In IBD or blocks were disconnected without any new ones
120-
return;
117+
namespace {
121118

122-
for (auto i = notifiers.begin(); i!=notifiers.end(); )
123-
{
124-
CZMQAbstractNotifier *notifier = i->get();
125-
if (notifier->NotifyBlock(pindexNew))
126-
{
127-
i++;
128-
}
129-
else
130-
{
119+
template <typename Function>
120+
void TryForEachAndRemoveFailed(std::list<std::unique_ptr<CZMQAbstractNotifier>>& notifiers, const Function& func)
121+
{
122+
for (auto i = notifiers.begin(); i != notifiers.end(); ) {
123+
CZMQAbstractNotifier* notifier = i->get();
124+
if (func(notifier)) {
125+
++i;
126+
} else {
131127
notifier->Shutdown();
132128
i = notifiers.erase(i);
133129
}
134130
}
135131
}
136132

133+
} // anonymous namespace
134+
135+
void CZMQNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
136+
{
137+
if (fInitialDownload || pindexNew == pindexFork) // In IBD or blocks were disconnected without any new ones
138+
return;
139+
140+
TryForEachAndRemoveFailed(notifiers, [pindexNew](CZMQAbstractNotifier* notifier) {
141+
return notifier->NotifyBlock(pindexNew);
142+
});
143+
}
144+
137145
void CZMQNotificationInterface::TransactionAddedToMempool(const CTransactionRef& ptx)
138146
{
139147
// Used by BlockConnected and BlockDisconnected as well, because they're
140148
// all the same external callback.
141149
const CTransaction& tx = *ptx;
142150

143-
for (auto i = notifiers.begin(); i!=notifiers.end(); )
144-
{
145-
CZMQAbstractNotifier *notifier = i->get();
146-
if (notifier->NotifyTransaction(tx))
147-
{
148-
i++;
149-
}
150-
else
151-
{
152-
notifier->Shutdown();
153-
i = notifiers.erase(i);
154-
}
155-
}
151+
TryForEachAndRemoveFailed(notifiers, [&tx](CZMQAbstractNotifier* notifier) {
152+
return notifier->NotifyTransaction(tx);
153+
});
156154
}
157155

158156
void CZMQNotificationInterface::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexConnected)

0 commit comments

Comments
 (0)