From 189f524195fc17ed94f36f1b99ff7e24e3a3018f Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Sun, 12 Apr 2015 18:33:43 +0200 Subject: [PATCH] Make SynchronizationPoint interruptible SMACK-632 --- .../smack/bosh/XMPPBOSHConnection.java | 2 +- .../smack/SynchronizationPoint.java | 26 +++++++------------ .../smack/tcp/XMPPTCPConnection.java | 3 ++- 3 files changed, 13 insertions(+), 18 deletions(-) diff --git a/smack-bosh/src/main/java/org/jivesoftware/smack/bosh/XMPPBOSHConnection.java b/smack-bosh/src/main/java/org/jivesoftware/smack/bosh/XMPPBOSHConnection.java index 46c3f8ebe..4151ef086 100644 --- a/smack-bosh/src/main/java/org/jivesoftware/smack/bosh/XMPPBOSHConnection.java +++ b/smack-bosh/src/main/java/org/jivesoftware/smack/bosh/XMPPBOSHConnection.java @@ -132,7 +132,7 @@ public class XMPPBOSHConnection extends AbstractXMPPConnection { } @Override - protected void connectInternal() throws SmackException { + protected void connectInternal() throws SmackException, InterruptedException { done = false; try { // Ensure a clean starting state diff --git a/smack-core/src/main/java/org/jivesoftware/smack/SynchronizationPoint.java b/smack-core/src/main/java/org/jivesoftware/smack/SynchronizationPoint.java index 3402299ce..853438778 100644 --- a/smack-core/src/main/java/org/jivesoftware/smack/SynchronizationPoint.java +++ b/smack-core/src/main/java/org/jivesoftware/smack/SynchronizationPoint.java @@ -19,8 +19,6 @@ package org.jivesoftware.smack; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; -import java.util.logging.Level; -import java.util.logging.Logger; import org.jivesoftware.smack.SmackException.NoResponseException; import org.jivesoftware.smack.SmackException.NotConnectedException; @@ -30,8 +28,6 @@ import org.jivesoftware.smack.packet.PlainStreamElement; public class SynchronizationPoint { - private static final Logger LOGGER = Logger.getLogger(SynchronizationPoint.class.getName()); - private final AbstractXMPPConnection connection; private final Lock connectionLock; private final Condition condition; @@ -120,8 +116,9 @@ public class SynchronizationPoint { * Check if this synchronization point is successful or wait the connections reply timeout. * @throws NoResponseException if there was no response marking the synchronization point as success or failed. * @throws E if there was a failure + * @throws InterruptedException */ - public void checkIfSuccessOrWaitOrThrow() throws NoResponseException, E { + public void checkIfSuccessOrWaitOrThrow() throws NoResponseException, E, InterruptedException { checkIfSuccessOrWait(); if (state == State.Failure) { throw failureException; @@ -131,8 +128,9 @@ public class SynchronizationPoint { /** * Check if this synchronization point is successful or wait the connections reply timeout. * @throws NoResponseException if there was no response marking the synchronization point as success or failed. + * @throws InterruptedException */ - public void checkIfSuccessOrWait() throws NoResponseException { + public void checkIfSuccessOrWait() throws NoResponseException, InterruptedException { connectionLock.lock(); try { if (state == State.Success) { @@ -222,20 +220,16 @@ public class SynchronizationPoint { * {@link #reportSuccess()}, {@link #reportFailure()} and {@link #reportFailure(Exception)} will either set this * synchronization point to {@link State#Success} or {@link State#Failure}. If none of them is set after the * connections reply timeout, this method will set the state of {@link State#NoResponse}. + * @throws InterruptedException */ - private void waitForConditionOrTimeout() { + private void waitForConditionOrTimeout() throws InterruptedException { long remainingWait = TimeUnit.MILLISECONDS.toNanos(connection.getPacketReplyTimeout()); while (state == State.RequestSent || state == State.Initial) { - try { - if (remainingWait <= 0) { - state = State.NoResponse; - break; - } - remainingWait = condition.awaitNanos(remainingWait); - } catch (InterruptedException e) { - // This InterruptedException could be "spurious wakeups", see javadoc of awaitNanos() - LOGGER.log(Level.WARNING, "Thread interrupt while waiting for condition or timeout ignored", e); + if (remainingWait <= 0) { + state = State.NoResponse; + break; } + remainingWait = condition.awaitNanos(remainingWait); } } diff --git a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java index 575edbb7f..9507d7dfa 100644 --- a/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java +++ b/smack-tcp/src/main/java/org/jivesoftware/smack/tcp/XMPPTCPConnection.java @@ -1239,6 +1239,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection { /** * Shuts down the stanza(/packet) writer. Once this method has been called, no further * packets will be written to the server. + * @throws InterruptedException */ void shutdown(boolean instant) { instantShutdown = instant; @@ -1247,7 +1248,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection { try { shutdownDone.checkIfSuccessOrWait(); } - catch (NoResponseException e) { + catch (NoResponseException | InterruptedException e) { LOGGER.log(Level.WARNING, "shutdownDone was not marked as successful by the writer thread", e); } }