1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2024-12-22 10:37:59 +01:00

[muc] Prevent race condition on enter() by waiting

This prevents a race condition of enter() with the presence listern by
waiting until all presences have been processed.

Reported-by: Guus der Kinderen <guus@goodbytes.nl>
This commit is contained in:
Florian Schmaus 2020-11-08 21:46:06 +01:00
parent f12fe2264a
commit 7e311ab9df

View file

@ -149,6 +149,11 @@ public class MultiUserChat {
private EntityFullJid myRoomJid; private EntityFullJid myRoomJid;
private StanzaCollector messageCollector; private StanzaCollector messageCollector;
/**
* Used to signal that the reflected self-presence was received <b>and</b> processed by us.
*/
private volatile boolean processedReflectedSelfPresence;
MultiUserChat(XMPPConnection connection, EntityBareJid room, MultiUserChatManager multiUserChatManager) { MultiUserChat(XMPPConnection connection, EntityBareJid room, MultiUserChatManager multiUserChatManager) {
this.connection = connection; this.connection = connection;
this.room = room; this.room = room;
@ -216,13 +221,15 @@ public class MultiUserChat {
newAffiliation, newAffiliation,
isUserStatusModification, isUserStatusModification,
from); from);
} } else if (mucUser.getStatus().contains(MUCUser.Status.PRESENCE_TO_SELF_110)) {
else { processedReflectedSelfPresence = true;
synchronized (this) {
notify();
}
} else {
// A new occupant has joined the room // A new occupant has joined the room
if (!isUserStatusModification) { for (ParticipantStatusListener listener : participantStatusListeners) {
for (ParticipantStatusListener listener : participantStatusListeners) { listener.joined(from);
listener.joined(from);
}
} }
} }
break; break;
@ -376,6 +383,7 @@ public class MultiUserChat {
) )
); );
// @formatter:on // @formatter:on
processedReflectedSelfPresence = false;
StanzaCollector presenceStanzaCollector = null; StanzaCollector presenceStanzaCollector = null;
final Presence reflectedSelfPresence; final Presence reflectedSelfPresence;
try { try {
@ -398,6 +406,16 @@ public class MultiUserChat {
} }
} }
synchronized (presenceListener) {
// Only continue after we have received *and* processed the reflected self-presence. Since presences are
// handled in an extra listener, we may return from enter() without having processed all presences of the
// participants, resulting in a e.g. to low participant counter after enter(). Hence we wait here until the
// processing is done.
while (!processedReflectedSelfPresence) {
presenceListener.wait();
}
}
// This presence must be send from a full JID. We use the resourcepart of this JID as nick, since the room may // This presence must be send from a full JID. We use the resourcepart of this JID as nick, since the room may
// performed roomnick rewriting // performed roomnick rewriting
Resourcepart receivedNickname = reflectedSelfPresence.getFrom().getResourceOrThrow(); Resourcepart receivedNickname = reflectedSelfPresence.getFrom().getResourceOrThrow();