Skip to content

Commit 831b0ec

Browse files
committed
Merge #13686: ZMQ: Small cleanups in the ZMQ code
6fe2ef2 scripted-diff: Rename SendMessage to SendZmqMessage. (Daniel Kraft) a3ffb6e Replace zmqconfig.h by a simple zmqutil. (Daniel Kraft) 7f2ad1b Use std::unique_ptr for CZMQNotifierFactory. (Daniel Kraft) b93b9d5 Simplify and fix notifier removal on error. (Daniel Kraft) e15b1cf Various cleanups in zmqnotificationinterface. (Daniel Kraft) Pull request description: This contains various small code cleanups that make the ZMQ code easier to read and maintain (at least in my opinion). The only functional change is that a potential memory leak is fixed that would have occured when a notifier is removed from the `notifiers` list after its callback function returned `false` (which is likely not relevant in practice but still a bug). ACKs for top commit: instagibbs: utACK 6fe2ef2 hebasto: re-ACK 6fe2ef2, only the latest commit got a scripted-diff since my [previous](bitcoin/bitcoin#13686 (review)) review. Tree-SHA512: 8206f8713bf3698d7cd4cb235f6657dc1c4dd920f50a8c5f371a559dd17ce5ab6d94d6281165eef860a22fc844a6bb25489ada12c83ebc780efd7ccdc0860f70
2 parents 83b2384 + 6fe2ef2 commit 831b0ec

10 files changed

+103
-109
lines changed

src/Makefile.am

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -263,10 +263,10 @@ BITCOIN_CORE_H = \
263263
walletinitinterface.h \
264264
warnings.h \
265265
zmq/zmqabstractnotifier.h \
266-
zmq/zmqconfig.h\
267266
zmq/zmqnotificationinterface.h \
268267
zmq/zmqpublishnotifier.h \
269-
zmq/zmqrpc.h
268+
zmq/zmqrpc.h \
269+
zmq/zmqutil.h
270270

271271

272272
obj/build.h: FORCE
@@ -345,7 +345,8 @@ libbitcoin_zmq_a_SOURCES = \
345345
zmq/zmqabstractnotifier.cpp \
346346
zmq/zmqnotificationinterface.cpp \
347347
zmq/zmqpublishnotifier.cpp \
348-
zmq/zmqrpc.cpp
348+
zmq/zmqrpc.cpp \
349+
zmq/zmqutil.cpp
349350
endif
350351

351352

src/zmq/zmqabstractnotifier.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
#include <zmq/zmqabstractnotifier.h>
66

7+
#include <cassert>
8+
79
const int CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM;
810

911
CZMQAbstractNotifier::~CZMQAbstractNotifier()

src/zmq/zmqabstractnotifier.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,16 @@
55
#ifndef BITCOIN_ZMQ_ZMQABSTRACTNOTIFIER_H
66
#define BITCOIN_ZMQ_ZMQABSTRACTNOTIFIER_H
77

8-
#include <zmq/zmqconfig.h>
8+
#include <util/memory.h>
9+
10+
#include <memory>
11+
#include <string>
912

1013
class CBlockIndex;
14+
class CTransaction;
1115
class CZMQAbstractNotifier;
1216

13-
typedef CZMQAbstractNotifier* (*CZMQNotifierFactory)();
17+
using CZMQNotifierFactory = std::unique_ptr<CZMQAbstractNotifier> (*)();
1418

1519
class CZMQAbstractNotifier
1620
{
@@ -21,9 +25,9 @@ class CZMQAbstractNotifier
2125
virtual ~CZMQAbstractNotifier();
2226

2327
template <typename T>
24-
static CZMQAbstractNotifier* Create()
28+
static std::unique_ptr<CZMQAbstractNotifier> Create()
2529
{
26-
return new T();
30+
return MakeUnique<T>();
2731
}
2832

2933
std::string GetType() const { return type; }

src/zmq/zmqconfig.h

Lines changed: 0 additions & 22 deletions
This file was deleted.

src/zmq/zmqnotificationinterface.cpp

Lines changed: 44 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -4,77 +4,66 @@
44

55
#include <zmq/zmqnotificationinterface.h>
66
#include <zmq/zmqpublishnotifier.h>
7+
#include <zmq/zmqutil.h>
8+
9+
#include <zmq.h>
710

811
#include <validation.h>
912
#include <util/system.h>
1013

11-
void zmqError(const char *str)
12-
{
13-
LogPrint(BCLog::ZMQ, "zmq: Error: %s, errno=%s\n", str, zmq_strerror(errno));
14-
}
15-
1614
CZMQNotificationInterface::CZMQNotificationInterface() : pcontext(nullptr)
1715
{
1816
}
1917

2018
CZMQNotificationInterface::~CZMQNotificationInterface()
2119
{
2220
Shutdown();
23-
24-
for (std::list<CZMQAbstractNotifier*>::iterator i=notifiers.begin(); i!=notifiers.end(); ++i)
25-
{
26-
delete *i;
27-
}
2821
}
2922

3023
std::list<const CZMQAbstractNotifier*> CZMQNotificationInterface::GetActiveNotifiers() const
3124
{
3225
std::list<const CZMQAbstractNotifier*> result;
33-
for (const auto* n : notifiers) {
34-
result.push_back(n);
26+
for (const auto& n : notifiers) {
27+
result.push_back(n.get());
3528
}
3629
return result;
3730
}
3831

3932
CZMQNotificationInterface* CZMQNotificationInterface::Create()
4033
{
41-
CZMQNotificationInterface* notificationInterface = nullptr;
4234
std::map<std::string, CZMQNotifierFactory> factories;
43-
std::list<CZMQAbstractNotifier*> notifiers;
44-
4535
factories["pubhashblock"] = CZMQAbstractNotifier::Create<CZMQPublishHashBlockNotifier>;
4636
factories["pubhashtx"] = CZMQAbstractNotifier::Create<CZMQPublishHashTransactionNotifier>;
4737
factories["pubrawblock"] = CZMQAbstractNotifier::Create<CZMQPublishRawBlockNotifier>;
4838
factories["pubrawtx"] = CZMQAbstractNotifier::Create<CZMQPublishRawTransactionNotifier>;
4939

40+
std::list<std::unique_ptr<CZMQAbstractNotifier>> notifiers;
5041
for (const auto& entry : factories)
5142
{
5243
std::string arg("-zmq" + entry.first);
5344
if (gArgs.IsArgSet(arg))
5445
{
55-
CZMQNotifierFactory factory = entry.second;
56-
std::string address = gArgs.GetArg(arg, "");
57-
CZMQAbstractNotifier *notifier = factory();
46+
const auto& factory = entry.second;
47+
const std::string address = gArgs.GetArg(arg, "");
48+
std::unique_ptr<CZMQAbstractNotifier> notifier = factory();
5849
notifier->SetType(entry.first);
5950
notifier->SetAddress(address);
6051
notifier->SetOutboundMessageHighWaterMark(static_cast<int>(gArgs.GetArg(arg + "hwm", CZMQAbstractNotifier::DEFAULT_ZMQ_SNDHWM)));
61-
notifiers.push_back(notifier);
52+
notifiers.push_back(std::move(notifier));
6253
}
6354
}
6455

6556
if (!notifiers.empty())
6657
{
67-
notificationInterface = new CZMQNotificationInterface();
68-
notificationInterface->notifiers = notifiers;
58+
std::unique_ptr<CZMQNotificationInterface> notificationInterface(new CZMQNotificationInterface());
59+
notificationInterface->notifiers = std::move(notifiers);
6960

70-
if (!notificationInterface->Initialize())
71-
{
72-
delete notificationInterface;
73-
notificationInterface = nullptr;
61+
if (notificationInterface->Initialize()) {
62+
return notificationInterface.release();
7463
}
7564
}
7665

77-
return notificationInterface;
66+
return nullptr;
7867
}
7968

8069
// Called at startup to conditionally set up ZMQ socket(s)
@@ -95,26 +84,15 @@ bool CZMQNotificationInterface::Initialize()
9584
return false;
9685
}
9786

98-
std::list<CZMQAbstractNotifier*>::iterator i=notifiers.begin();
99-
for (; i!=notifiers.end(); ++i)
100-
{
101-
CZMQAbstractNotifier *notifier = *i;
102-
if (notifier->Initialize(pcontext))
103-
{
87+
for (auto& notifier : notifiers) {
88+
if (notifier->Initialize(pcontext)) {
10489
LogPrint(BCLog::ZMQ, "zmq: Notifier %s ready (address = %s)\n", notifier->GetType(), notifier->GetAddress());
105-
}
106-
else
107-
{
90+
} else {
10891
LogPrint(BCLog::ZMQ, "zmq: Notifier %s failed (address = %s)\n", notifier->GetType(), notifier->GetAddress());
109-
break;
92+
return false;
11093
}
11194
}
11295

113-
if (i!=notifiers.end())
114-
{
115-
return false;
116-
}
117-
11896
return true;
11997
}
12098

@@ -124,9 +102,7 @@ void CZMQNotificationInterface::Shutdown()
124102
LogPrint(BCLog::ZMQ, "zmq: Shutdown notification interface\n");
125103
if (pcontext)
126104
{
127-
for (std::list<CZMQAbstractNotifier*>::iterator i=notifiers.begin(); i!=notifiers.end(); ++i)
128-
{
129-
CZMQAbstractNotifier *notifier = *i;
105+
for (auto& notifier : notifiers) {
130106
LogPrint(BCLog::ZMQ, "zmq: Shutdown notifier %s at %s\n", notifier->GetType(), notifier->GetAddress());
131107
notifier->Shutdown();
132108
}
@@ -136,45 +112,43 @@ void CZMQNotificationInterface::Shutdown()
136112
}
137113
}
138114

139-
void CZMQNotificationInterface::UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload)
140-
{
141-
if (fInitialDownload || pindexNew == pindexFork) // In IBD or blocks were disconnected without any new ones
142-
return;
115+
namespace {
143116

144-
for (std::list<CZMQAbstractNotifier*>::iterator i = notifiers.begin(); i!=notifiers.end(); )
145-
{
146-
CZMQAbstractNotifier *notifier = *i;
147-
if (notifier->NotifyBlock(pindexNew))
148-
{
149-
i++;
150-
}
151-
else
152-
{
117+
template <typename Function>
118+
void TryForEachAndRemoveFailed(std::list<std::unique_ptr<CZMQAbstractNotifier>>& notifiers, const Function& func)
119+
{
120+
for (auto i = notifiers.begin(); i != notifiers.end(); ) {
121+
CZMQAbstractNotifier* notifier = i->get();
122+
if (func(notifier)) {
123+
++i;
124+
} else {
153125
notifier->Shutdown();
154126
i = notifiers.erase(i);
155127
}
156128
}
157129
}
158130

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

165-
for (std::list<CZMQAbstractNotifier*>::iterator i = notifiers.begin(); i!=notifiers.end(); )
166-
{
167-
CZMQAbstractNotifier *notifier = *i;
168-
if (notifier->NotifyTransaction(tx))
169-
{
170-
i++;
171-
}
172-
else
173-
{
174-
notifier->Shutdown();
175-
i = notifiers.erase(i);
176-
}
177-
}
149+
TryForEachAndRemoveFailed(notifiers, [&tx](CZMQAbstractNotifier* notifier) {
150+
return notifier->NotifyTransaction(tx);
151+
});
178152
}
179153

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

src/zmq/zmqnotificationinterface.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <validationinterface.h>
99
#include <list>
10+
#include <memory>
1011

1112
class CBlockIndex;
1213
class CZMQAbstractNotifier;
@@ -34,7 +35,7 @@ class CZMQNotificationInterface final : public CValidationInterface
3435
CZMQNotificationInterface();
3536

3637
void *pcontext;
37-
std::list<CZMQAbstractNotifier*> notifiers;
38+
std::list<std::unique_ptr<CZMQAbstractNotifier>> notifiers;
3839
};
3940

4041
extern CZMQNotificationInterface* g_zmq_notification_interface;

src/zmq/zmqpublishnotifier.cpp

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,23 @@
22
// Distributed under the MIT software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

5+
#include <zmq/zmqpublishnotifier.h>
6+
57
#include <chain.h>
68
#include <chainparams.h>
9+
#include <rpc/server.h>
710
#include <streams.h>
8-
#include <zmq/zmqpublishnotifier.h>
9-
#include <validation.h>
1011
#include <util/system.h>
11-
#include <rpc/server.h>
12+
#include <validation.h>
13+
#include <zmq/zmqutil.h>
14+
15+
#include <zmq.h>
16+
17+
#include <cstdarg>
18+
#include <cstddef>
19+
#include <map>
20+
#include <string>
21+
#include <utility>
1222

1323
static std::multimap<std::string, CZMQAbstractPublishNotifier*> mapPublishNotifiers;
1424

@@ -149,7 +159,7 @@ void CZMQAbstractPublishNotifier::Shutdown()
149159
psocket = nullptr;
150160
}
151161

152-
bool CZMQAbstractPublishNotifier::SendMessage(const char *command, const void* data, size_t size)
162+
bool CZMQAbstractPublishNotifier::SendZmqMessage(const char *command, const void* data, size_t size)
153163
{
154164
assert(psocket);
155165

@@ -173,7 +183,7 @@ bool CZMQPublishHashBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
173183
char data[32];
174184
for (unsigned int i = 0; i < 32; i++)
175185
data[31 - i] = hash.begin()[i];
176-
return SendMessage(MSG_HASHBLOCK, data, 32);
186+
return SendZmqMessage(MSG_HASHBLOCK, data, 32);
177187
}
178188

179189
bool CZMQPublishHashTransactionNotifier::NotifyTransaction(const CTransaction &transaction)
@@ -183,7 +193,7 @@ bool CZMQPublishHashTransactionNotifier::NotifyTransaction(const CTransaction &t
183193
char data[32];
184194
for (unsigned int i = 0; i < 32; i++)
185195
data[31 - i] = hash.begin()[i];
186-
return SendMessage(MSG_HASHTX, data, 32);
196+
return SendZmqMessage(MSG_HASHTX, data, 32);
187197
}
188198

189199
bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
@@ -204,7 +214,7 @@ bool CZMQPublishRawBlockNotifier::NotifyBlock(const CBlockIndex *pindex)
204214
ss << block;
205215
}
206216

207-
return SendMessage(MSG_RAWBLOCK, &(*ss.begin()), ss.size());
217+
return SendZmqMessage(MSG_RAWBLOCK, &(*ss.begin()), ss.size());
208218
}
209219

210220
bool CZMQPublishRawTransactionNotifier::NotifyTransaction(const CTransaction &transaction)
@@ -213,5 +223,5 @@ bool CZMQPublishRawTransactionNotifier::NotifyTransaction(const CTransaction &tr
213223
LogPrint(BCLog::ZMQ, "zmq: Publish rawtx %s\n", hash.GetHex());
214224
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION | RPCSerializationFlags());
215225
ss << transaction;
216-
return SendMessage(MSG_RAWTX, &(*ss.begin()), ss.size());
226+
return SendZmqMessage(MSG_RAWTX, &(*ss.begin()), ss.size());
217227
}

src/zmq/zmqpublishnotifier.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class CZMQAbstractPublishNotifier : public CZMQAbstractNotifier
2222
* data
2323
* message sequence number
2424
*/
25-
bool SendMessage(const char *command, const void* data, size_t size);
25+
bool SendZmqMessage(const char *command, const void* data, size_t size);
2626

2727
bool Initialize(void *pcontext) override;
2828
void Shutdown() override;

0 commit comments

Comments
 (0)