There is a race condition when maintaining/checking message acknowledgements
for a subscription when messages are pushed to the client.
i.e. when the client asks for a message and there are none, the client is registered
as wanting a message and when a message arrives, the message is sent to the client.
This involves maintaining a "list" of unacknowledged messages for that client/subscription
which must be checked before we allow removal of the the subscription during close.
However, for pushing the maintenance of the unacknowledged messages can
race with the close of the subscription because they are not maintained in the same synchronized block
as deciding the client wants the message.
Subscription found = null;
// In this synchronized block we decide that a client wants the message
if (receivers.size() != 0)
for (Iterator it = receivers.iterator(); it.hasNext()
Subscription sub = (Subscription) it.next();
But only later outside this block do we maintain the unacknowledged messages
// Queue to the receiver
if (found != null)
This means that during the ... above a close of the subscription which leads to an invocation
of hasUnackedMessages() could decide there are no unacknoweldged messages.