I got 2 functions. The first one discoverHosts() sends an request message to other computers. After this it goes to sleep with the await command. A separate threat calls the handleMessage() function when he receives a response. After he handles the response he uses notifyAll() to let discoderHosts() know that he has to check that all responses are received.
DiscoverHosts() does await when he calls the function. However when the separate threat calls handleMessage(), discoverHosts() doesn't awake when handleMessage calls the signalAll(). I checked while debuggig if signalAll() is called and this is the case. I have almost the same bit of code somewhere else in my project where it does work.
Do any of you guys know what I am overlooking?
private final Lock lock = new ReentrantLock();
private final Condition allReceived = lock.newCondition();
private void discoverHosts() throws Exception {
lock.lock();
externalNodes = new HashMap<String, NodeAddress>();
Message msg = new Message(null, "REQUEST_IP");
logger.debug("Broadcasting ip request, waiting responses");
channel.send(msg);
// TODO:Write a time-out
while (channel.getView().size() - 1 != externalNodes.keySet().size()) {
logger.debug("Channel: " + (channel.getView().size() - 1));
logger.debug("Responses: "+ externalNodes.keySet().size());
allReceived.await();
}
logger.debug("All answers received");
lock.unlock();
}
protected void handleMessage(Message msg) {
lock.lock();
if (!((String) msg.getObject()).matches("IP_RESPONSE:[0-9.]*"))
return;
logger.debug("Received answer from " + msg.getObject());
String ip = ((String) msg.getObject()).replaceAll("IP_RESPONSE:", "");
// externalHostIps.add(ip);
NodeAddress currentAddress = new NodeAddress(ip, msg.getSrc());
externalNodes.put(ip, currentAddress);
logger.debug("Signalling all threads");
allReceived.signalAll();
lock.unlock();
logger.debug("Unlocked");
}
Logger output:
4372 [main] DEBUG com.conbit.webhackarena.monitor.monitor.Monitor@3b91eb - Broadcasting ip request, waiting responses
4372 [main] DEBUG com.conbit.webhackarena.monitor.monitor.Monitor@3b91eb - Channel: 1
4372 [main] DEBUG com.conbit.webhackarena.monitor.monitor.Monitor@3b91eb - Responses: 0
4394 [Incoming-1,webhackarena,leendert-K53SV-53745] DEBUG com.conbit.webhackarena.monitor.monitor.Monitor@3b91eb - Received answer from IP_RESPONSE:192.168.1.106
4396 [Incoming-1,webhackarena,leendert-K53SV-53745] DEBUG com.conbit.webhackarena.monitor.monitor.Monitor@3b91eb - Signalling all threads
4397 [Incoming-1,webhackarena,leendert-K53SV-53745] DEBUG com.conbit.webhackarena.monitor.monitor.Monitor@3b91eb - Unlocked
I think your problem is this line
if (!((String) msg.getObject()).matches("IP_RESPONSE:[0-9.]*"))
return;
Which means under some condition you acquire the lock and never release it.
Always use try...finally
blocks with Lock
to avoid this issue.
protected void handleMessage(Message msg) {
lock.lock();
try {
if (!((String) msg.getObject()).matches("IP_RESPONSE:[0-9.]*"))
return;
logger.debug("Received answer from " + msg.getObject());
String ip = ((String) msg.getObject()).replaceAll("IP_RESPONSE:", "");
// externalHostIps.add(ip);
NodeAddress currentAddress = new NodeAddress(ip, msg.getSrc());
externalNodes.put(ip, currentAddress);
logger.debug("Signalling all threads");
allReceived.signalAll();
} finally {
lock.unlock();
}
}