Merge branch '283-die-bluetooth-die' into 'master'

Ensure key agreement tasks finish if they ignore interrupts

The problem here was that `BluetoothSocket#connect()` was throwing an IOException when the task was interrupted - the task treated this like any other connection failure and retried, so the task never finished.

The fix is to check whether the timeout has expired before retrying, so the task eventually finishes even if it ignores the original interrupt.

Closes #283

See merge request !443
This commit is contained in:
Torsten Grote
2016-12-06 11:02:19 +00:00
2 changed files with 15 additions and 11 deletions

View File

@@ -341,8 +341,10 @@ class DroidtoothPlugin implements DuplexPlugin {
LOG.info("Connected to " + scrubMacAddress(address)); LOG.info("Connected to " + scrubMacAddress(address));
return s; return s;
} catch (IOException e) { } catch (IOException e) {
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO)) {
LOG.info("Failed to connect to " + scrubMacAddress(address)); LOG.info("Failed to connect to " + scrubMacAddress(address)
+ ": " + e);
}
tryToClose(s); tryToClose(s);
return null; return null;
} }
@@ -588,9 +590,10 @@ class DroidtoothPlugin implements DuplexPlugin {
finished.countDown(); finished.countDown();
} else if (action.equals(FOUND)) { } else if (action.equals(FOUND)) {
BluetoothDevice d = intent.getParcelableExtra(EXTRA_DEVICE); BluetoothDevice d = intent.getParcelableExtra(EXTRA_DEVICE);
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO)) {
LOG.info("Discovered device: " + LOG.info("Discovered device: " +
scrubMacAddress(d.getAddress())); scrubMacAddress(d.getAddress()));
}
addresses.add(d.getAddress()); addresses.add(d.getAddress());
} }
} }

View File

@@ -148,9 +148,9 @@ class KeyAgreementConnector {
private void closePending(@Nullable KeyAgreementConnection chosen) { private void closePending(@Nullable KeyAgreementConnection chosen) {
for (Future<KeyAgreementConnection> f : pending) { for (Future<KeyAgreementConnection> f : pending) {
try { try {
if (f.cancel(true)) if (f.cancel(true)) {
LOG.info("Cancelled task"); LOG.info("Cancelled task");
else if (!f.isCancelled()) { } else if (!f.isCancelled()) {
KeyAgreementConnection c = f.get(); KeyAgreementConnection c = f.get();
if (c != null && c != chosen) if (c != null && c != chosen)
tryToClose(c.getConnection(), false); tryToClose(c.getConnection(), false);
@@ -193,9 +193,10 @@ class KeyAgreementConnector {
@Override @Override
public KeyAgreementConnection call() throws Exception { public KeyAgreementConnection call() throws Exception {
// Repeat attempts until we connect or get interrupted // Repeat attempts until we connect, get interrupted, or time out
while (true) { while (true) {
long now = clock.currentTimeMillis(); long now = clock.currentTimeMillis();
if (now > end) throw new IOException();
DuplexTransportConnection conn = DuplexTransportConnection conn =
plugin.createKeyAgreementConnection(commitment, plugin.createKeyAgreementConnection(commitment,
descriptor, end - now); descriptor, end - now);
@@ -221,8 +222,7 @@ class KeyAgreementConnector {
} }
@Override @Override
public KeyAgreementConnection call() public KeyAgreementConnection call() throws Exception {
throws Exception {
KeyAgreementConnection c = connectionTask.call(); KeyAgreementConnection c = connectionTask.call();
InputStream in = c.getConnection().getReader().getInputStream(); InputStream in = c.getConnection().getReader().getInputStream();
boolean waitingSent = false; boolean waitingSent = false;
@@ -232,13 +232,14 @@ class KeyAgreementConnector {
callbacks.connectionWaiting(); callbacks.connectionWaiting();
waitingSent = true; waitingSent = true;
} }
if (LOG.isLoggable(INFO)) if (LOG.isLoggable(INFO)) {
LOG.info(c.getTransportId().toString() + LOG.info(c.getTransportId().getString() +
": Waiting for connection"); ": Waiting for connection");
}
Thread.sleep(1000); Thread.sleep(1000);
} }
if (!alice && LOG.isLoggable(INFO)) if (!alice && LOG.isLoggable(INFO))
LOG.info(c.getTransportId().toString() + ": Data available"); LOG.info(c.getTransportId().getString() + ": Data available");
return c; return c;
} }
} }