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 d1db32361..da961fd85 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
@@ -1292,6 +1292,13 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
return shutdownTimestamp != null;
}
+ private void throwNotConnectedExceptionIfDoneAndResumptionNotPossible() throws NotConnectedException {
+ if (done() && !isSmResumptionPossible()) {
+ // Don't throw a NotConnectedException is there is an resumable stream available
+ throw new NotConnectedException();
+ }
+ }
+
/**
* Sends the specified element to the server.
*
@@ -1299,16 +1306,20 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
* @throws NotConnectedException
*/
protected void sendStreamElement(Element element) throws NotConnectedException {
- if (done() && !isSmResumptionPossible()) {
- // Don't throw a NotConnectedException is there is an resumable stream available
- throw new NotConnectedException();
- }
+ throwNotConnectedExceptionIfDoneAndResumptionNotPossible();
- try {
- queue.put(element);
- }
- catch (InterruptedException ie) {
- throw new NotConnectedException();
+ boolean enqueued = false;
+ while (!enqueued) {
+ try {
+ queue.put(element);
+ enqueued = true;
+ }
+ catch (InterruptedException e) {
+ throwNotConnectedExceptionIfDoneAndResumptionNotPossible();
+ // If the method above did not throw, we have a spurious interrupt and we should try to enqueue the
+ // element again
+ LOGGER.log(Level.FINE, "Spurious interrupt", e);
+ }
}
}
@@ -1329,23 +1340,21 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
}
/**
- * Returns the next available element from the queue for writing.
+ * Maybe return the next available element from the queue for writing. If the queue is shut down or a
+ * spurious interrupt occurs, null
is returned. So it is important to check the 'done' condition in
+ * that case.
*
- * @return the next element for writing.
+ * @return the next element for writing or null.
*/
private Element nextStreamElement() {
- // TODO not sure if nextStreamElement and/or this done() condition still required.
- // Couldn't this be done in writePackets too?
- if (done()) {
- return null;
- }
-
Element packet = null;
try {
packet = queue.take();
}
catch (InterruptedException e) {
- // Do nothing
+ if (!queue.isShutdown()) {
+ LOGGER.log(Level.FINER, "Spurious interrupt", e);
+ }
}
return packet;
}
@@ -1391,9 +1400,7 @@ public class XMPPTCPConnection extends AbstractXMPPConnection {
}
}
if (!instantShutdown) {
- // Flush out the rest of the queue. If the queue is extremely large, it's
- // possible we won't have time to entirely flush it before the socket is forced
- // closed by the shutdown process.
+ // Flush out the rest of the queue.
try {
while (!queue.isEmpty()) {
Element packet = queue.remove();