summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Young <consult.awy@gmail.com>2015-04-28 10:28:12 (GMT)
committerAlan Young <consult.awy@gmail.com>2015-05-01 08:17:31 (GMT)
commitcd8e073cabc9a39abb14527b6e968ece1586b7ec (patch)
treeae2655de2bc46e632e6f75a6150d742b26813d00
parentde8538282dfbb73212fa241638147a64bbe9cee5 (diff)
downloadstroke-cd8e073cabc9a39abb14527b6e968ece1586b7ec.zip
stroke-cd8e073cabc9a39abb14527b6e968ece1586b7ec.tar.bz2
Revisit handling of JavaConnection race conditions.
JavaConnection.disconnect() can be called at any time when opening or using the connection. Its use can interfere with tests for selector_.isOpen(). Protect relevant code by synchronization blocks. This should not cause any contended synchronization issue as contention can only occur while disconnecting. This reverts the relevant part of 7d2101b9. Move selector_.select() call to end of Worker.run() while loop so that any write that is done while still connecting (if that is permitted and possible), and before selector_ first become non-null, is still picked up. Remove redundant checks on disconnecting_ and calls to handleDisconnected(null). Move a couple of fields which are only used in Worker nested class into Worker. Update copyright. Change-Id: I2eabad79c69fe4e9206942c8025e0ac012bffdb0
-rw-r--r--src/com/isode/stroke/network/JavaConnection.java64
1 files changed, 32 insertions, 32 deletions
diff --git a/src/com/isode/stroke/network/JavaConnection.java b/src/com/isode/stroke/network/JavaConnection.java
index 9b171d9..34f332b 100644
--- a/src/com/isode/stroke/network/JavaConnection.java
+++ b/src/com/isode/stroke/network/JavaConnection.java
@@ -1,8 +1,4 @@
/*
- * Copyright (c) 2010 Remko Tronçon
- * All rights reserved.
- */
-/*
* Copyright (c) 2010-2015, Isode Limited, London, England.
* All rights reserved.
*/
@@ -52,6 +48,8 @@ public class JavaConnection extends Connection implements EventOwner {
private final HostAddressPort address_;
private final List<byte[]> writeBuffer_ = Collections.synchronizedList(new ArrayList<byte[]>());
+ private SelectionKey selectionKey_;
+ private boolean disconnected_ = false;
public Worker(HostAddressPort address) {
address_ = address;
@@ -77,26 +75,9 @@ public class JavaConnection extends Connection implements EventOwner {
return;
}
handleConnected(false);
+
while (!disconnecting_) {
-
- /* This will block until something is ready on the selector,
- * including someone calling selector.wakeup(), or until the
- * thread is interrupted
- */
- try {
- selector_.select();
- } catch (IOException e) {
- disconnected_ = true;
- handleDisconnected(null);
- break;
- }
-
/* Something(s) happened. See what needs doing */
- if (disconnecting_) {
- handleDisconnected(null);
- /* No point doing anything else */
- break;
- }
boolean writeNeeded = isWriteNeeded();
boolean readNeeded = selectionKey_.isReadable();
@@ -148,7 +129,18 @@ public class JavaConnection extends Connection implements EventOwner {
*/
selector_.wakeup();
}
- }
+
+ /* This will block until something is ready on the selector,
+ * including someone calling selector.wakeup(), or until the
+ * thread is interrupted
+ */
+ try {
+ selector_.select();
+ } catch (IOException e) {
+ disconnected_ = true;
+ break;
+ }
+ }
handleDisconnected(null);
} finally {
if(socketChannel_ != null) {
@@ -159,8 +151,9 @@ public class JavaConnection extends Connection implements EventOwner {
}
if(selector_ != null) {
try {
- selector_.close();
- selector_ = null;
+ synchronized (selectorLock_) {
+ selector_.close();
+ }
} catch (IOException e) {
}
}
@@ -343,8 +336,12 @@ public class JavaConnection extends Connection implements EventOwner {
disconnecting_ = true;
// Check "isOpen" to Avoid Android crash see
// https://code.google.com/p/android/issues/detail?id=80785
- if (selector_ != null && selector_.isOpen()) {
- selector_.wakeup();
+ if (selector_ != null) {
+ synchronized (selectorLock_) {
+ if (selector_.isOpen()) {
+ selector_.wakeup();
+ }
+ }
}
}
@@ -353,8 +350,12 @@ public class JavaConnection extends Connection implements EventOwner {
worker_.writeBuffer_.add(data.getData());
// Check "isOpen" to Avoid Android crash see
// https://code.google.com/p/android/issues/detail?id=80785
- if (selector_ != null && selector_.isOpen()) {
- selector_.wakeup();
+ if (selector_ != null) {
+ synchronized (selectorLock_) {
+ if (selector_.isOpen()) {
+ selector_.wakeup();
+ }
+ }
}
}
@@ -381,10 +382,9 @@ public class JavaConnection extends Connection implements EventOwner {
private final EventLoop eventLoop_;
private boolean disconnecting_ = false;
- private boolean disconnected_ = false;
private SocketChannel socketChannel_;
- private volatile Selector selector_;
- private SelectionKey selectionKey_;
+ private Selector selector_;
+ private final Object selectorLock_ = new Object(); // use private lock object that is not visible elsewhere
private Worker worker_;
}