From 105c74b22bce25ee98a8f68ef65f5c8885abddfc Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Tue, 5 Oct 2021 20:47:35 +0200 Subject: [PATCH] [muc] Call userHasLeft() *after* the leave presence was sent Calling userHasLeft before sending the leave presence may result in invalid state as the MUC presence lister may modify the MUCs local state, e.g., occupantsMap, conurrently with the leave operation. If we reset it after the leave presence was send and acknowledged, then this can not happen as the server will not longer send any MUC related presences to us. Also fixes SMACK-914. In theory 52a49769f9a8 ("[muc] Check for self-presence first in presence listener") alone would fix SMACK-914, but this also fixes it indepentendly of 52a49769f9a8. Both commits are sensible, so both are applied. --- .../org/jivesoftware/smackx/muc/MultiUserChat.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChat.java b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChat.java index 800b50555..6e10a66ea 100644 --- a/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChat.java +++ b/smack-extensions/src/main/java/org/jivesoftware/smackx/muc/MultiUserChat.java @@ -789,11 +789,14 @@ public class MultiUserChat { StanzaFilter reflectedLeavePresenceFilter = new AndFilter(reflectedLeavePresenceFilters); - // Reset occupant information first so that we are assume that we left the room even if sendStanza() would - // throw. - userHasLeft(); - - Presence reflectedLeavePresence = connection.createStanzaCollectorAndSend(reflectedLeavePresenceFilter, leavePresence).nextResultOrThrow(); + Presence reflectedLeavePresence; + try { + reflectedLeavePresence = connection.createStanzaCollectorAndSend(reflectedLeavePresenceFilter, leavePresence).nextResultOrThrow(); + } finally { + // Reset occupant information after we send the leave presence. This ensures that we only call userHasLeft() + // and reset the local MUC state after we successfully left the MUC (or if an exception occurred). + userHasLeft(); + } return reflectedLeavePresence; }