diff --git a/briar-core/src/org/briarproject/lifecycle/LifecycleManagerImpl.java b/briar-core/src/org/briarproject/lifecycle/LifecycleManagerImpl.java
index b227943116e713cd5a277e7ad2699583b3149a7d..3abfa4cbc3ac732a2cff9c66bf5c2f9395580350 100644
--- a/briar-core/src/org/briarproject/lifecycle/LifecycleManagerImpl.java
+++ b/briar-core/src/org/briarproject/lifecycle/LifecycleManagerImpl.java
@@ -53,20 +53,20 @@ class LifecycleManagerImpl implements LifecycleManager {
 	@Override
 	public void registerService(Service s) {
 		if (LOG.isLoggable(INFO))
-			LOG.info("Registering service " + s.getClass().getName());
+			LOG.info("Registering service " + s.getClass().getSimpleName());
 		services.add(s);
 	}
 
 	@Override
 	public void registerClient(Client c) {
 		if (LOG.isLoggable(INFO))
-			LOG.info("Registering client " + c.getClass().getName());
+			LOG.info("Registering client " + c.getClass().getSimpleName());
 		clients.add(c);
 	}
 
 	@Override
 	public void registerForShutdown(ExecutorService e) {
-		LOG.info("Registering executor");
+		LOG.info("Registering executor " + e.getClass().getSimpleName());
 		executors.add(e);
 	}
 
@@ -94,7 +94,8 @@ class LifecycleManagerImpl implements LifecycleManager {
 					c.createLocalState(txn);
 					duration = System.currentTimeMillis() - start;
 					if (LOG.isLoggable(INFO)) {
-						LOG.info("Starting client " + c.getClass().getName()
+						LOG.info("Starting client "
+								+ c.getClass().getSimpleName()
 								+ " took " + duration + " ms");
 					}
 				}
@@ -107,7 +108,7 @@ class LifecycleManagerImpl implements LifecycleManager {
 				s.startService();
 				duration = System.currentTimeMillis() - start;
 				if (LOG.isLoggable(INFO)) {
-					LOG.info("Starting service " + s.getClass().getName()
+					LOG.info("Starting service " + s.getClass().getSimpleName()
 							+ " took " + duration + " ms");
 				}
 			}
@@ -140,13 +141,17 @@ class LifecycleManagerImpl implements LifecycleManager {
 				s.stopService();
 				long duration = System.currentTimeMillis() - start;
 				if (LOG.isLoggable(INFO)) {
-					LOG.info("Stopping service " + s.getClass().getName()
+					LOG.info("Stopping service " + s.getClass().getSimpleName()
 							+ " took " + duration + " ms");
 				}
 			}
-			for (ExecutorService e : executors) e.shutdownNow();
-			if (LOG.isLoggable(INFO))
-				LOG.info(executors.size() + " executors shut down");
+			for (ExecutorService e : executors) {
+				if (LOG.isLoggable(INFO)) {
+					LOG.info("Stopping executor "
+							+ e.getClass().getSimpleName());
+				}
+				e.shutdownNow();
+			}
 			long start = System.currentTimeMillis();
 			db.close();
 			long duration = System.currentTimeMillis() - start;
diff --git a/briar-core/src/org/briarproject/plugins/PluginManagerImpl.java b/briar-core/src/org/briarproject/plugins/PluginManagerImpl.java
index 852fe3dc95221301df59daa30654a2d1b03931a2..e8b9b129d79120db7198b0dbcdad851d838d22bb 100644
--- a/briar-core/src/org/briarproject/plugins/PluginManagerImpl.java
+++ b/briar-core/src/org/briarproject/plugins/PluginManagerImpl.java
@@ -62,6 +62,7 @@ class PluginManagerImpl implements PluginManager, Service {
 	private final Map<TransportId, Plugin> plugins;
 	private final List<SimplexPlugin> simplexPlugins;
 	private final List<DuplexPlugin> duplexPlugins;
+	private final Map<TransportId, CountDownLatch> startLatches;
 	private final AtomicBoolean used = new AtomicBoolean(false);
 
 	@Inject
@@ -80,69 +81,64 @@ class PluginManagerImpl implements PluginManager, Service {
 		plugins = new ConcurrentHashMap<TransportId, Plugin>();
 		simplexPlugins = new CopyOnWriteArrayList<SimplexPlugin>();
 		duplexPlugins = new CopyOnWriteArrayList<DuplexPlugin>();
+		startLatches = new ConcurrentHashMap<TransportId, CountDownLatch>();
 	}
 
 	@Override
 	public void startService() throws ServiceException {
 		if (used.getAndSet(true)) throw new IllegalStateException();
-		Collection<SimplexPluginFactory> simplexFactories =
-				pluginConfig.getSimplexFactories();
-		Collection<DuplexPluginFactory> duplexFactories =
-				pluginConfig.getDuplexFactories();
-		int numPlugins = simplexFactories.size() + duplexFactories.size();
-		CountDownLatch latch = new CountDownLatch(numPlugins);
-		// Instantiate and start the simplex plugins
+		// Instantiate the simplex plugins and start them asynchronously
 		LOG.info("Starting simplex plugins");
-		for (SimplexPluginFactory f : simplexFactories) {
+		for (SimplexPluginFactory f : pluginConfig.getSimplexFactories()) {
 			TransportId t = f.getId();
 			SimplexPlugin s = f.createPlugin(new SimplexCallback(t));
 			if (s == null) {
 				if (LOG.isLoggable(WARNING))
 					LOG.warning("Could not create plugin for " + t);
-				latch.countDown();
 			} else {
 				plugins.put(t, s);
 				simplexPlugins.add(s);
-				ioExecutor.execute(new PluginStarter(s, latch));
+				CountDownLatch startLatch = new CountDownLatch(1);
+				startLatches.put(t, startLatch);
+				ioExecutor.execute(new PluginStarter(s, startLatch));
 			}
 		}
-		// Instantiate and start the duplex plugins
+		// Instantiate the duplex plugins and start them asynchronously
 		LOG.info("Starting duplex plugins");
-		for (DuplexPluginFactory f : duplexFactories) {
+		for (DuplexPluginFactory f : pluginConfig.getDuplexFactories()) {
 			TransportId t = f.getId();
 			DuplexPlugin d = f.createPlugin(new DuplexCallback(t));
 			if (d == null) {
 				if (LOG.isLoggable(WARNING))
 					LOG.warning("Could not create plugin for " + t);
-				latch.countDown();
 			} else {
 				plugins.put(t, d);
 				duplexPlugins.add(d);
-				ioExecutor.execute(new PluginStarter(d, latch));
+				CountDownLatch startLatch = new CountDownLatch(1);
+				startLatches.put(t, startLatch);
+				ioExecutor.execute(new PluginStarter(d, startLatch));
 			}
 		}
-		// Wait for all the plugins to start
-		try {
-			latch.await();
-		} catch (InterruptedException e) {
-			throw new ServiceException(e);
-		}
 	}
 
 	@Override
 	public void stopService() throws ServiceException {
-		CountDownLatch latch = new CountDownLatch(plugins.size());
+		CountDownLatch stopLatch = new CountDownLatch(plugins.size());
 		// Stop the simplex plugins
 		LOG.info("Stopping simplex plugins");
-		for (SimplexPlugin plugin : simplexPlugins)
-			ioExecutor.execute(new PluginStopper(plugin, latch));
+		for (SimplexPlugin s : simplexPlugins) {
+			CountDownLatch startLatch = startLatches.get(s.getId());
+			ioExecutor.execute(new PluginStopper(s, startLatch, stopLatch));
+		}
 		// Stop the duplex plugins
 		LOG.info("Stopping duplex plugins");
-		for (DuplexPlugin plugin : duplexPlugins)
-			ioExecutor.execute(new PluginStopper(plugin, latch));
+		for (DuplexPlugin d : duplexPlugins) {
+			CountDownLatch startLatch = startLatches.get(d.getId());
+			ioExecutor.execute(new PluginStopper(d, startLatch, stopLatch));
+		}
 		// Wait for all the plugins to stop
 		try {
-			latch.await();
+			stopLatch.await();
 		} catch (InterruptedException e) {
 			throw new ServiceException(e);
 		}
@@ -182,11 +178,11 @@ class PluginManagerImpl implements PluginManager, Service {
 	private class PluginStarter implements Runnable {
 
 		private final Plugin plugin;
-		private final CountDownLatch latch;
+		private final CountDownLatch startLatch;
 
-		private PluginStarter(Plugin plugin, CountDownLatch latch) {
+		private PluginStarter(Plugin plugin, CountDownLatch startLatch) {
 			this.plugin = plugin;
-			this.latch = latch;
+			this.startLatch = startLatch;
 		}
 
 		@Override
@@ -212,7 +208,7 @@ class PluginManagerImpl implements PluginManager, Service {
 						LOG.log(WARNING, e.toString(), e);
 				}
 			} finally {
-				latch.countDown();
+				startLatch.countDown();
 			}
 		}
 	}
@@ -220,16 +216,21 @@ class PluginManagerImpl implements PluginManager, Service {
 	private class PluginStopper implements Runnable {
 
 		private final Plugin plugin;
-		private final CountDownLatch latch;
+		private final CountDownLatch startLatch, stopLatch;
 
-		private PluginStopper(Plugin plugin, CountDownLatch latch) {
+		private PluginStopper(Plugin plugin, CountDownLatch startLatch,
+				CountDownLatch stopLatch) {
 			this.plugin = plugin;
-			this.latch = latch;
+			this.startLatch = startLatch;
+			this.stopLatch = stopLatch;
 		}
 
 		@Override
 		public void run() {
 			try {
+				// Wait for the plugin to finish starting
+				startLatch.await();
+				// Stop the plugin
 				long start = System.currentTimeMillis();
 				plugin.stop();
 				long duration = System.currentTimeMillis() - start;
@@ -237,10 +238,13 @@ class PluginManagerImpl implements PluginManager, Service {
 					LOG.info("Stopping plugin " + plugin.getId()
 							+ " took " + duration + " ms");
 				}
+			} catch (InterruptedException e) {
+				LOG.warning("Interrupted while waiting for plugin to start");
+				// This task runs on an executor, so don't reset the interrupt
 			} catch (IOException e) {
 				if (LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
 			} finally {
-				latch.countDown();
+				stopLatch.countDown();
 			}
 		}
 	}