From e47d4990c3b5d5e27d712c2717f86c44af0242c3 Mon Sep 17 00:00:00 2001
From: akwizgran <akwizgran@users.sourceforge.net>
Date: Fri, 9 Dec 2011 23:01:32 +0000
Subject: [PATCH] Fixed Bluetooth shutdown issues.

---
 .../plugins/bluetooth/BluetoothPlugin.java    | 27 +++++++++----------
 .../sf/briar/plugins/StreamClientTest.java    |  2 ++
 .../sf/briar/plugins/StreamServerTest.java    | 13 ++++-----
 test/net/sf/briar/plugins/StreamTest.java     |  2 --
 .../bluetooth/BluetoothClientTest.java        | 13 ++++++---
 .../bluetooth/BluetoothServerTest.java        | 13 ++++++---
 .../plugins/socket/LanSocketClientTest.java   | 12 ++++++---
 .../plugins/socket/LanSocketServerTest.java   | 13 ++++++---
 8 files changed, 58 insertions(+), 37 deletions(-)

diff --git a/components/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java b/components/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java
index 510035c964..253040533b 100644
--- a/components/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java
+++ b/components/net/sf/briar/plugins/bluetooth/BluetoothPlugin.java
@@ -4,9 +4,11 @@ import java.io.IOException;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Random;
+import java.util.Set;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
@@ -47,8 +49,7 @@ class BluetoothPlugin implements StreamPlugin {
 	private final long pollingInterval;
 	private final Object discoveryLock = new Object();
 	private final ScheduledExecutorService scheduler;
-	// Locking: this
-	private final Map<StreamConnectionNotifier, ScheduledFuture<?>> sockets;
+	private final Set<StreamConnectionNotifier> sockets; // Locking: this
 
 	private boolean running = false; // Locking: this
 	private LocalDevice localDevice = null; // Locking: this
@@ -60,7 +61,7 @@ class BluetoothPlugin implements StreamPlugin {
 		this.callback = callback;
 		this.pollingInterval = pollingInterval;
 		scheduler = Executors.newScheduledThreadPool(0);
-		sockets = new HashMap<StreamConnectionNotifier, ScheduledFuture<?>>();
+		sockets = new HashSet<StreamConnectionNotifier>();
 	}
 
 	public TransportId getId() {
@@ -176,10 +177,8 @@ class BluetoothPlugin implements StreamPlugin {
 	public synchronized void stop() {
 		running = false;
 		localDevice = null;
-		for(Entry<StreamConnectionNotifier, ScheduledFuture<?>> e
-				: sockets.entrySet()) {
-			if(e.getValue().cancel(false)) tryToClose(e.getKey());
-		}
+		scheduler.shutdownNow();
+		for(StreamConnectionNotifier scn : sockets) tryToClose(scn);
 		sockets.clear();
 		if(socket != null) {
 			tryToClose(socket);
@@ -389,6 +388,13 @@ class BluetoothPlugin implements StreamPlugin {
 			if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
 			return;
 		}
+		synchronized(this) {
+			if(!running) {
+				tryToClose(scn);
+				return;
+			}
+			sockets.add(scn);
+		}
 		// Close the socket when the invitation times out
 		Runnable close = new Runnable() {
 			public void run() {
@@ -400,13 +406,6 @@ class BluetoothPlugin implements StreamPlugin {
 		};
 		ScheduledFuture<?> future = scheduler.schedule(close,
 				c.getTimeout(), TimeUnit.MILLISECONDS);
-		synchronized(this) {
-			if(!running) {
-				if(future.cancel(false)) tryToClose(scn);
-				return;
-			}
-			sockets.put(scn, future);
-		}
 		// Try to accept a connection
 		try {
 			StreamConnection s = scn.acceptAndOpen();
diff --git a/test/net/sf/briar/plugins/StreamClientTest.java b/test/net/sf/briar/plugins/StreamClientTest.java
index d1ddbe0fea..2607099fcb 100644
--- a/test/net/sf/briar/plugins/StreamClientTest.java
+++ b/test/net/sf/briar/plugins/StreamClientTest.java
@@ -11,6 +11,8 @@ import net.sf.briar.api.transport.StreamTransportConnection;
 
 public abstract class StreamClientTest extends StreamTest {
 
+	protected ClientCallback callback = null;
+
 	protected void run() throws IOException {
 		assert plugin != null;
 		// Start the plugin
diff --git a/test/net/sf/briar/plugins/StreamServerTest.java b/test/net/sf/briar/plugins/StreamServerTest.java
index 5a03e9ec96..ecf65e76af 100644
--- a/test/net/sf/briar/plugins/StreamServerTest.java
+++ b/test/net/sf/briar/plugins/StreamServerTest.java
@@ -1,6 +1,7 @@
 package net.sf.briar.plugins;
 
 import java.util.Map;
+import java.util.concurrent.CountDownLatch;
 
 import net.sf.briar.api.ContactId;
 import net.sf.briar.api.TransportConfig;
@@ -10,6 +11,8 @@ import net.sf.briar.api.transport.StreamTransportConnection;
 
 public abstract class StreamServerTest extends StreamTest {
 
+	protected ServerCallback callback = null;
+
 	protected void run() throws Exception {
 		assert callback != null;
 		assert plugin != null;
@@ -18,9 +21,7 @@ public abstract class StreamServerTest extends StreamTest {
 		plugin.start();
 		// Wait for a connection
 		System.out.println("Waiting for connection");
-		synchronized(callback) {
-			callback.wait();
-		}
+		callback.latch.await();
 		// Try to accept an invitation
 		System.out.println("Accepting invitation");
 		StreamTransportConnection s = plugin.acceptInvitation(123,
@@ -47,6 +48,8 @@ public abstract class StreamServerTest extends StreamTest {
 
 	protected class ServerCallback implements StreamPluginCallback {
 
+		private final CountDownLatch latch = new CountDownLatch(1);
+
 		private TransportConfig config;
 		private TransportProperties local;
 		private Map<ContactId, TransportProperties> remote;
@@ -91,9 +94,7 @@ public abstract class StreamServerTest extends StreamTest {
 		public void incomingConnectionCreated(StreamTransportConnection s) {
 			System.out.println("Connection received");
 			sendChallengeReceiveResponse(s);
-			synchronized(this) {
-				notifyAll();
-			}
+			latch.countDown();
 		}
 
 		public void outgoingConnectionCreated(ContactId contactId,
diff --git a/test/net/sf/briar/plugins/StreamTest.java b/test/net/sf/briar/plugins/StreamTest.java
index 04dd55a3f7..ecb3f6bacf 100644
--- a/test/net/sf/briar/plugins/StreamTest.java
+++ b/test/net/sf/briar/plugins/StreamTest.java
@@ -6,7 +6,6 @@ import java.util.Scanner;
 
 import net.sf.briar.api.ContactId;
 import net.sf.briar.api.plugins.StreamPlugin;
-import net.sf.briar.api.plugins.StreamPluginCallback;
 import net.sf.briar.api.transport.StreamTransportConnection;
 
 abstract class StreamTest {
@@ -17,7 +16,6 @@ abstract class StreamTest {
 
 	protected final ContactId contactId = new ContactId(0);
 
-	protected StreamPluginCallback callback = null;
 	protected StreamPlugin plugin = null;
 
 	protected void sendChallengeReceiveResponse(StreamTransportConnection s) {
diff --git a/test/net/sf/briar/plugins/bluetooth/BluetoothClientTest.java b/test/net/sf/briar/plugins/bluetooth/BluetoothClientTest.java
index e1acd2dae5..4e464e7c3c 100644
--- a/test/net/sf/briar/plugins/bluetooth/BluetoothClientTest.java
+++ b/test/net/sf/briar/plugins/bluetooth/BluetoothClientTest.java
@@ -2,8 +2,9 @@ package net.sf.briar.plugins.bluetooth;
 
 import java.util.Collections;
 import java.util.Map;
-import java.util.concurrent.Executors;
 import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 
 import net.sf.briar.api.ContactId;
 import net.sf.briar.api.TransportConfig;
@@ -14,7 +15,7 @@ import net.sf.briar.plugins.StreamClientTest;
 // is running on another machine
 public class BluetoothClientTest extends StreamClientTest {
 
-	private BluetoothClientTest(String serverAddress) {
+	private BluetoothClientTest(Executor executor, String serverAddress) {
 		// Store the server's Bluetooth address and UUID
 		TransportProperties p = new TransportProperties();
 		p.put("address", serverAddress);
@@ -24,7 +25,6 @@ public class BluetoothClientTest extends StreamClientTest {
 		// Create the plugin
 		callback = new ClientCallback(new TransportConfig(),
 				new TransportProperties(), remote);
-		Executor executor = Executors.newCachedThreadPool();
 		plugin = new BluetoothPlugin(executor, callback, 0L);
 	}
 
@@ -33,6 +33,11 @@ public class BluetoothClientTest extends StreamClientTest {
 			System.err.println("Please specify the server's Bluetooth address");
 			System.exit(1);
 		}
-		new BluetoothClientTest(args[0]).run();
+		ExecutorService executor = Executors.newCachedThreadPool();
+		try {
+			new BluetoothClientTest(executor, args[0]).run();
+		} finally {
+			executor.shutdown();
+		}
 	}
 }
diff --git a/test/net/sf/briar/plugins/bluetooth/BluetoothServerTest.java b/test/net/sf/briar/plugins/bluetooth/BluetoothServerTest.java
index 81d28cad27..956edff546 100644
--- a/test/net/sf/briar/plugins/bluetooth/BluetoothServerTest.java
+++ b/test/net/sf/briar/plugins/bluetooth/BluetoothServerTest.java
@@ -1,8 +1,9 @@
 package net.sf.briar.plugins.bluetooth;
 
 import java.util.Collections;
-import java.util.concurrent.Executors;
 import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 
 import net.sf.briar.api.TransportConfig;
 import net.sf.briar.api.TransportProperties;
@@ -12,18 +13,22 @@ import net.sf.briar.plugins.StreamServerTest;
 // is running on another machine
 public class BluetoothServerTest extends StreamServerTest {
 
-	private BluetoothServerTest() {
+	private BluetoothServerTest(Executor executor) {
 		// Store the UUID
 		TransportProperties local = new TransportProperties();
 		local.put("uuid", BluetoothTest.UUID);
 		// Create the plugin
 		callback = new ServerCallback(new TransportConfig(), local,
 				Collections.singletonMap(contactId, new TransportProperties()));
-		Executor executor = Executors.newCachedThreadPool();
 		plugin = new BluetoothPlugin(executor, callback, 0L);
 	}
 
 	public static void main(String[] args) throws Exception {
-		new BluetoothServerTest().run();
+		ExecutorService executor = Executors.newCachedThreadPool();
+		try {
+			new BluetoothServerTest(executor).run();
+		} finally {
+			executor.shutdown();
+		}
 	}
 }
diff --git a/test/net/sf/briar/plugins/socket/LanSocketClientTest.java b/test/net/sf/briar/plugins/socket/LanSocketClientTest.java
index bc99d5ae6b..6031b4b721 100644
--- a/test/net/sf/briar/plugins/socket/LanSocketClientTest.java
+++ b/test/net/sf/briar/plugins/socket/LanSocketClientTest.java
@@ -2,6 +2,7 @@ package net.sf.briar.plugins.socket;
 
 import java.util.Collections;
 import java.util.Map;
+import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.Executor;
 
@@ -14,7 +15,8 @@ import net.sf.briar.plugins.StreamClientTest;
 // is running on another machine
 public class LanSocketClientTest extends StreamClientTest {
 
-	private LanSocketClientTest(String serverAddress, String serverPort) {
+	private LanSocketClientTest(Executor executor, String serverAddress,
+			String serverPort) {
 		// Store the server's internal address and port
 		TransportProperties p = new TransportProperties();
 		p.put("internal", serverAddress);
@@ -24,7 +26,6 @@ public class LanSocketClientTest extends StreamClientTest {
 		// Create the plugin
 		callback = new ClientCallback(new TransportConfig(),
 				new TransportProperties(), remote);
-		Executor executor = Executors.newCachedThreadPool();
 		plugin = new LanSocketPlugin(executor, callback, 0L);
 	}
 
@@ -33,6 +34,11 @@ public class LanSocketClientTest extends StreamClientTest {
 			System.err.println("Please specify the server's address and port");
 			System.exit(1);
 		}
-		new LanSocketClientTest(args[0], args[1]).run();
+		ExecutorService executor = Executors.newCachedThreadPool();
+		try {
+			new LanSocketClientTest(executor, args[0], args[1]).run();
+		} finally {
+			executor.shutdown();
+		}
 	}
 }
diff --git a/test/net/sf/briar/plugins/socket/LanSocketServerTest.java b/test/net/sf/briar/plugins/socket/LanSocketServerTest.java
index b969600b10..cf88b3b23f 100644
--- a/test/net/sf/briar/plugins/socket/LanSocketServerTest.java
+++ b/test/net/sf/briar/plugins/socket/LanSocketServerTest.java
@@ -1,8 +1,9 @@
 package net.sf.briar.plugins.socket;
 
 import java.util.Collections;
-import java.util.concurrent.Executors;
 import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 
 import net.sf.briar.api.TransportConfig;
 import net.sf.briar.api.TransportProperties;
@@ -12,15 +13,19 @@ import net.sf.briar.plugins.StreamServerTest;
 // is running on another machine
 public class LanSocketServerTest extends StreamServerTest {
 
-	private LanSocketServerTest() {
+	private LanSocketServerTest(Executor executor) {
 		callback = new ServerCallback(new TransportConfig(),
 				new TransportProperties(),
 				Collections.singletonMap(contactId, new TransportProperties()));
-		Executor executor = Executors.newCachedThreadPool();
 		plugin = new LanSocketPlugin(executor, callback, 0L);
 	}
 
 	public static void main(String[] args) throws Exception {
-		new LanSocketServerTest().run();
+		ExecutorService executor = Executors.newCachedThreadPool();
+		try {
+			new LanSocketServerTest(executor).run();
+		} finally {
+			executor.shutdown();
+		}
 	}
 }
-- 
GitLab