From 92f253cc74a436388b15369e370bd96c3e19713a Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Wed, 28 Sep 2022 13:52:58 +0200 Subject: [PATCH] [core] Replace AbstractXMPPConnection.inOrderListeners Using AsyncButOrdered for the receive listeners means that a listener may not have been yet run once invokeStanzaCollectorsAndNotifyRecvListeners() returnes. This can lead to deadlocks as reported by Boris Grozev [1]. Fixes SMACK-927. 1: https://discourse.igniterealtime.org/t/thread-stuck-in-multiuserchat-enter-forever/92090 --- .../org/jivesoftware/smack/AbstractXMPPConnection.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java b/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java index 5a3ae04ac..0e710ee03 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/AbstractXMPPConnection.java @@ -33,6 +33,7 @@ import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.Semaphore; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; @@ -348,8 +349,6 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { protected static final AsyncButOrdered ASYNC_BUT_ORDERED = new AsyncButOrdered<>(); - protected final AsyncButOrdered inOrderListeners = new AsyncButOrdered<>(); - /** * The used host to establish the connection to */ @@ -1613,8 +1612,9 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { listenersToNotify.clear(); extractMatchingListeners(packet, recvListeners, listenersToNotify); + final Semaphore listenerSemaphore = new Semaphore(1 - listenersToNotify.size()); for (StanzaListener stanzaListener : listenersToNotify) { - inOrderListeners.performAsyncButOrdered(stanzaListener, () -> { + asyncGoLimited(() -> { try { stanzaListener.processStanza(packet); } @@ -1623,9 +1623,12 @@ public abstract class AbstractXMPPConnection implements XMPPConnection { } catch (Exception e) { LOGGER.log(Level.SEVERE, "Exception in packet listener", e); + } finally { + listenerSemaphore.release(); } }); } + listenerSemaphore.acquireUninterruptibly(); // Notify the receive listeners interested in the packet listenersToNotify.clear();