fixed interupt handling

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/xml/TagWriter.java       |  4 
src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java | 46 +++-
2 files changed, 33 insertions(+), 17 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/xml/TagWriter.java 🔗

@@ -27,7 +27,9 @@ public class TagWriter {
 				try {
 					AbstractStanza output = writeQueue.take();
 					outputStream.write(output.toString());
-					outputStream.flush();
+					if (writeQueue.size() == 0) {
+						outputStream.flush();
+					}
 				} catch (Exception e) {
 					return;
 				}

src/main/java/eu/siacs/conversations/xmpp/XmppConnection.java 🔗

@@ -37,6 +37,8 @@ import java.util.Hashtable;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map.Entry;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.regex.Matcher;
@@ -145,6 +147,8 @@ public class XmppConnection implements Runnable {
 	private SaslMechanism saslMechanism;
 	private URL redirectionUrl = null;
 	private String verifiedHostname = null;
+	private Thread mThread;
+	private CountDownLatch mStreamCountDownLatch;
 
 	private class MyKeyManager implements X509KeyManager {
 		@Override
@@ -502,7 +506,8 @@ public class XmppConnection implements Runnable {
 	@Override
 	public void run() {
 		synchronized (this) {
-			if (Thread.currentThread().isInterrupted()) {
+			this.mThread = Thread.currentThread();
+			if (this.mThread.isInterrupted()) {
 				Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": aborting connect because thread was interrupted");
 				return;
 			}
@@ -512,6 +517,8 @@ public class XmppConnection implements Runnable {
 	}
 
 	private void processStream() throws XmlPullParserException, IOException, NoSuchAlgorithmException {
+		final CountDownLatch streamCountDownLatch = new CountDownLatch(1);
+		this.mStreamCountDownLatch = streamCountDownLatch;
 		Tag nextTag = tagReader.readTag();
 		while (nextTag != null && !nextTag.isEnd("stream")) {
 			if (nextTag.isStart("error")) {
@@ -681,6 +688,9 @@ public class XmppConnection implements Runnable {
 			}
 			nextTag = tagReader.readTag();
 		}
+		if (nextTag != null && nextTag.isEnd("stream")) {
+			streamCountDownLatch.countDown();
+		}
 	}
 
 	private void acknowledgeStanzaUpTo(int serverCount) {
@@ -1460,7 +1470,9 @@ public class XmppConnection implements Runnable {
 	}
 
 	public void interrupt() {
-		Thread.currentThread().interrupt();
+		if (this.mThread != null) {
+			this.mThread.interrupt();
+		}
 	}
 
 	public void disconnect(final boolean force) {
@@ -1469,28 +1481,30 @@ public class XmppConnection implements Runnable {
 		if (force) {
 			forceCloseSocket();
 		} else {
-			if (tagWriter.isActive()) {
-				tagWriter.finish();
-				final Socket currentSocket = socket;
+			final TagWriter currentTagWriter = this.tagWriter;
+			if (currentTagWriter.isActive()) {
+				currentTagWriter.finish();
+				final Socket currentSocket = this.socket;
+				final CountDownLatch streamCountDownLatch = this.mStreamCountDownLatch;
 				try {
-					for (int i = 0; i <= 10 && !tagWriter.finished() && !currentSocket.isClosed(); ++i) {
-						uninterruptedSleep(100);
+					for (int i = 0; i <= 10 && !currentTagWriter.finished() && !currentSocket.isClosed(); ++i) {
+						Thread.sleep(100);
 					}
 					Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": closing stream");
-					tagWriter.writeTag(Tag.end("stream:stream"));
-					for (int i = 0; i <= 20 && !currentSocket.isClosed(); ++i) {
-						uninterruptedSleep(100);
-					}
-					if (currentSocket.isClosed()) {
-						Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": remote closed socket");
-					} else {
-						Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": remote has not closed socket. force closing");
+					currentTagWriter.writeTag(Tag.end("stream:stream"));
+					if (streamCountDownLatch != null) {
+							if (streamCountDownLatch.await(1, TimeUnit.SECONDS)) {
+							Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": remote ended stream");
+						} else {
+							Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": remote has not closed socket. force closing");
+						}
 					}
+				} catch (InterruptedException e) {
+					Log.d(Config.LOGTAG,account.getJid().toBareJid()+": interrupted while gracefully closing stream");
 				} catch (final IOException e) {
 					Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": io exception during disconnect (" + e.getMessage() + ")");
 				} finally {
 					FileBackend.close(currentSocket);
-					forceCloseSocket();
 				}
 			} else {
 				forceCloseSocket();