]
Bela Ban commented on JGRP-2103:
--------------------------------
The point of passing the listener as arg to the call itself, rather than setting it later,
is exactly to prevent the scenario you hit.
GroupRequest times out when the only recipient leaves too soon
--------------------------------------------------------------
Key: JGRP-2103
URL:
https://issues.jboss.org/browse/JGRP-2103
Project: JGroups
Issue Type: Bug
Affects Versions: 3.6.10
Reporter: Dan Berindei
Assignee: Bela Ban
Fix For: 3.6.12
There is a concurrency issue when a user calls {{messageDispatcher.cast(dests, msg,
options, block_for_results, null)}} and adds a listener later with
{{req.setListener(listener)}}.
If the node installs a new view between {{cast()}} and {{setListener()}} that removes all
the {{dests}} nodes, the listener is never called. This test fails:
{code}
public void testCastToMissingNode() throws Exception {
d1.setRequestHandler(new MyHandler(new byte[10]));
b = createChannel(a);
b.setName("B");
final CountDownLatch targetLatch = new CountDownLatch(1);
d2 = new MessageDispatcher(b, null, null, new RequestHandler() {
@Override
public Object handle(Message msg) throws Exception {
targetLatch.await();
return null;
}
});
b.connect("MessageDispatcherUnitTest");
Assert.assertEquals(2, b.getView().size());
final CountDownLatch futureLatch = new CountDownLatch(1);
FutureListener listener = new FutureListener() {
@Override
public void futureDone(Future future) {
futureLatch.countDown();
}
};
List<Address> dests = Collections.singletonList(b.getAddress());
byte[] buf = new byte[1];
Message msg = new Message();
msg.setBuffer(buf);
NotifyingFuture<RspList<Object>> future =
d1.castMessageWithFuture(dests, msg, RequestOptions.SYNC(), null);
b.disconnect();
Thread.sleep(100);
future.setListener(listener);
assertTrue(futureLatch.await(10, TimeUnit.SECONDS));
targetLatch.countDown();
}
{code}
If I change the {{d1.castMessageWithFuture(dests, msg, RequestOptions.SYNC(), null)}}
with {{d1.castMessageWithFuture(dests, msg, RequestOptions.SYNC(), listener)}} and comment
out the {{future.setListener(listener)}} line, the test passes.