Skip to content

Commit 83a6ce5

Browse files
committed
Unbind EventBroadcaster socket before destruction
1 parent 8ed921e commit 83a6ce5

2 files changed

Lines changed: 76 additions & 59 deletions

File tree

Source/Plugins/EventBroadcaster/EventBroadcaster.cpp

Lines changed: 72 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ CriticalSection EventBroadcaster::sharedContextLock{};
1717
EventBroadcaster::ZMQContext::ZMQContext(const ScopedLock& lock)
1818
#ifdef ZEROMQ
1919
: context(zmq_ctx_new())
20+
#else
21+
: context(nullptr)
2022
#endif
2123
{
2224
sharedContext = this;
@@ -38,11 +40,14 @@ void* EventBroadcaster::ZMQContext::createZMQSocket()
3840
#ifdef ZEROMQ
3941
jassert(context != nullptr);
4042
return zmq_socket(context, ZMQ_PUB);
43+
#else
44+
return nullptr;
4145
#endif
4246
}
4347

4448
EventBroadcaster::ZMQSocket::ZMQSocket()
45-
: socket(nullptr)
49+
: socket (nullptr)
50+
, boundPort (0)
4651
{
4752
ScopedLock lock(sharedContextLock);
4853
if (sharedContext == nullptr)
@@ -64,6 +69,7 @@ EventBroadcaster::ZMQSocket::ZMQSocket()
6469
EventBroadcaster::ZMQSocket::~ZMQSocket()
6570
{
6671
#ifdef ZEROMQ
72+
unbind(); // do this explicitly to free the port immediately
6773
zmq_close(socket);
6874
#endif
6975
}
@@ -73,6 +79,11 @@ bool EventBroadcaster::ZMQSocket::isValid() const
7379
return socket != nullptr;
7480
}
7581

82+
int EventBroadcaster::ZMQSocket::getBoundPort() const
83+
{
84+
return boundPort;
85+
}
86+
7687
int EventBroadcaster::ZMQSocket::send(const void* buf, size_t len, int flags)
7788
{
7889
#ifdef ZEROMQ
@@ -86,18 +97,31 @@ int EventBroadcaster::ZMQSocket::bind(int port)
8697
#ifdef ZEROMQ
8798
if (isValid() && port != 0)
8899
{
89-
return zmq_bind(socket, getEndpoint(port).toRawUTF8());
100+
int status = unbind();
101+
if (status == 0)
102+
{
103+
status = zmq_bind(socket, getEndpoint(port).toRawUTF8());
104+
if (status == 0)
105+
{
106+
boundPort = port;
107+
}
108+
}
109+
return status;
90110
}
91111
#endif
92112
return 0;
93113
}
94114

95-
int EventBroadcaster::ZMQSocket::unbind(int port)
115+
int EventBroadcaster::ZMQSocket::unbind()
96116
{
97117
#ifdef ZEROMQ
98-
if (isValid() && port != 0)
118+
if (isValid() && boundPort != 0)
99119
{
100-
return zmq_unbind(socket, getEndpoint(port).toRawUTF8());
120+
int status = zmq_unbind(socket, getEndpoint(boundPort).toRawUTF8());
121+
if (status == 0)
122+
{
123+
boundPort = 0;
124+
}
101125
}
102126
#endif
103127
return 0;
@@ -109,19 +133,9 @@ String EventBroadcaster::getEndpoint(int port)
109133
return String("tcp://*:") + String(port);
110134
}
111135

112-
void EventBroadcaster::reportActualListeningPort(int port)
113-
{
114-
listeningPort = port;
115-
auto editor = static_cast<EventBroadcasterEditor*>(getEditor());
116-
if (editor)
117-
{
118-
editor->setDisplayedPort(port);
119-
}
120-
}
121136

122137
EventBroadcaster::EventBroadcaster()
123138
: GenericProcessor ("Event Broadcaster")
124-
, listeningPort (0)
125139
{
126140
setProcessorType (PROCESSOR_TYPE_SINK);
127141

@@ -143,62 +157,65 @@ AudioProcessorEditor* EventBroadcaster::createEditor()
143157

144158
int EventBroadcaster::getListeningPort() const
145159
{
146-
return listeningPort;
160+
if (zmqSocket == nullptr) { return 0; }
161+
return zmqSocket->getBoundPort();
147162
}
148163

149164

150165
int EventBroadcaster::setListeningPort(int port, bool forceRestart)
151166
{
152-
if ((listeningPort != port) || forceRestart)
167+
int currPort = getListeningPort();
168+
if (currPort == port && !forceRestart)
153169
{
170+
return 0;
171+
}
172+
173+
int status = 0;
174+
154175
#ifdef ZEROMQ
155-
// unbind current socket (if any) to free up port
156-
if (zmqSocket != nullptr)
157-
{
158-
zmqSocket->unbind(listeningPort);
159-
}
176+
// unbind current socket (if any) to free up port
177+
if (zmqSocket != nullptr)
178+
{
179+
zmqSocket->unbind();
180+
}
160181

161-
ScopedPointer<ZMQSocket> newSocket = new ZMQSocket();
162-
auto editor = static_cast<EventBroadcasterEditor*>(getEditor());
163-
int status = 0;
182+
ScopedPointer<ZMQSocket> newSocket = new ZMQSocket();
164183

165-
if (!newSocket->isValid())
184+
if (!newSocket->isValid())
185+
{
186+
status = zmq_errno();
187+
std::cout << "Failed to create socket: " << zmq_strerror(status) << std::endl;
188+
}
189+
else
190+
{
191+
if (0 != newSocket->bind(port))
166192
{
167193
status = zmq_errno();
168-
std::cout << "Failed to create socket: " << zmq_strerror(status) << std::endl;
194+
std::cout << "Failed to bind to port " << port << ": "
195+
<< zmq_strerror(status) << std::endl;
169196
}
170197
else
171198
{
172-
if (0 != newSocket->bind(port))
173-
{
174-
status = zmq_errno();
175-
std::cout << "Failed to create socket: " << zmq_strerror(status) << std::endl;
176-
}
177-
else
178-
{
179-
// success
180-
zmqSocket = newSocket;
181-
reportActualListeningPort(port);
182-
return status;
183-
}
199+
// success
200+
zmqSocket = newSocket;
184201
}
202+
}
203+
204+
if (status != 0 && zmqSocket)
205+
{
206+
// try to rebind current socket to previous port
207+
zmqSocket->bind(currPort);
208+
}
185209

186-
// failure, try to rebind current socket to previous port
187-
if (zmqSocket != nullptr && 0 == zmqSocket->bind(listeningPort))
188-
{
189-
reportActualListeningPort(listeningPort);
190-
}
191-
else
192-
{
193-
reportActualListeningPort(0);
194-
}
195-
return status;
196-
#else
197-
reportActualListeningPort(port);
198-
return 0;
199210
#endif
211+
212+
// update editor
213+
auto editor = static_cast<EventBroadcasterEditor*>(getEditor());
214+
if (editor)
215+
{
216+
editor->setDisplayedPort(getListeningPort());
200217
}
201-
return -1;
218+
return status;
202219
}
203220

204221

@@ -241,7 +258,7 @@ void EventBroadcaster::handleSpike(const SpikeChannel* channelInfo, const MidiMe
241258
void EventBroadcaster::saveCustomParametersToXml(XmlElement* parentElement)
242259
{
243260
XmlElement* mainNode = parentElement->createNewChildElement("EVENTBROADCASTER");
244-
mainNode->setAttribute("port", listeningPort);
261+
mainNode->setAttribute("port", getListeningPort());
245262
}
246263

247264

@@ -253,7 +270,7 @@ void EventBroadcaster::loadCustomParametersFromXml()
253270
{
254271
if (mainNode->hasTagName("EVENTBROADCASTER"))
255272
{
256-
setListeningPort(mainNode->getIntAttribute("port"));
273+
setListeningPort(mainNode->getIntAttribute("port", getListeningPort()));
257274
}
258275
}
259276
}

Source/Plugins/EventBroadcaster/EventBroadcaster.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,19 +59,20 @@ class EventBroadcaster : public GenericProcessor
5959
~ZMQSocket();
6060

6161
bool isValid() const;
62+
int getBoundPort() const;
6263

6364
int send(const void* buf, size_t len, int flags);
6465
int bind(int port);
65-
int unbind(int port);
66+
int unbind();
6667
private:
68+
int boundPort;
6769
void* socket;
6870
ReferenceCountedObjectPtr<ZMQContext> context;
6971
};
7072

7173
void sendEvent(const MidiMessage& event, float eventSampleRate) const;
74+
7275
static String getEndpoint(int port);
73-
// called from getListeningPort() depending on success/failure of ZMQ operations
74-
void reportActualListeningPort(int port);
7576

7677
// share a "dumb" pointer that doesn't take part in reference counting.
7778
// want the context to be terminated by the time the static members are
@@ -80,7 +81,6 @@ class EventBroadcaster : public GenericProcessor
8081
static CriticalSection sharedContextLock;
8182

8283
ScopedPointer<ZMQSocket> zmqSocket;
83-
int listeningPort;
8484
};
8585

8686

0 commit comments

Comments
 (0)