mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-11-22 06:12:05 +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:
parent
f12fe2264a
commit
7e311ab9df
1 changed files with 24 additions and 6 deletions
|
@ -149,6 +149,11 @@ public class MultiUserChat {
|
|||
private EntityFullJid myRoomJid;
|
||||
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) {
|
||||
this.connection = connection;
|
||||
this.room = room;
|
||||
|
@ -216,15 +221,17 @@ public class MultiUserChat {
|
|||
newAffiliation,
|
||||
isUserStatusModification,
|
||||
from);
|
||||
} else if (mucUser.getStatus().contains(MUCUser.Status.PRESENCE_TO_SELF_110)) {
|
||||
processedReflectedSelfPresence = true;
|
||||
synchronized (this) {
|
||||
notify();
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
// A new occupant has joined the room
|
||||
if (!isUserStatusModification) {
|
||||
for (ParticipantStatusListener listener : participantStatusListeners) {
|
||||
listener.joined(from);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case unavailable:
|
||||
occupantsMap.remove(from);
|
||||
|
@ -376,6 +383,7 @@ public class MultiUserChat {
|
|||
)
|
||||
);
|
||||
// @formatter:on
|
||||
processedReflectedSelfPresence = false;
|
||||
StanzaCollector presenceStanzaCollector = null;
|
||||
final Presence reflectedSelfPresence;
|
||||
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
|
||||
// performed roomnick rewriting
|
||||
Resourcepart receivedNickname = reflectedSelfPresence.getFrom().getResourceOrThrow();
|
||||
|
|
Loading…
Reference in a new issue