diff --git a/components/net/sf/briar/plugins/file/PollingRemovableDriveMonitor.java b/components/net/sf/briar/plugins/file/PollingRemovableDriveMonitor.java
index 689ce99dd71b1f14ce404a39b827bc6712e5255e..73b86420a823f0089853125d6c9f6e9f57b5e737 100644
--- a/components/net/sf/briar/plugins/file/PollingRemovableDriveMonitor.java
+++ b/components/net/sf/briar/plugins/file/PollingRemovableDriveMonitor.java
@@ -12,7 +12,7 @@ import net.sf.briar.api.plugins.PluginExecutor;
 class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable {
 
 	private static final Logger LOG =
-		Logger.getLogger(PollingRemovableDriveMonitor.class.getName());
+			Logger.getLogger(PollingRemovableDriveMonitor.class.getName());
 
 	private final Executor pluginExecutor;
 	private final RemovableDriveFinder finder;
@@ -21,7 +21,6 @@ class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable {
 
 	private volatile boolean running = false;
 	private volatile Callback callback = null;
-	private volatile IOException exception = null;
 
 	public PollingRemovableDriveMonitor(@PluginExecutor Executor pluginExecutor,
 			RemovableDriveFinder finder, long pollingInterval) {
@@ -34,7 +33,6 @@ class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable {
 		synchronized(this) {
 			assert !running;
 			assert this.callback == null;
-			assert exception == null;
 			running = true;
 			this.callback = callback;
 		}
@@ -42,19 +40,15 @@ class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable {
 	}
 
 	public void stop() throws IOException {
-		IOException e;
 		synchronized(this) {
 			assert running;
 			assert callback != null;
 			running = false;
 			callback = null;
-			e = exception;
-			exception = null;
 		}
 		synchronized(pollingLock) {
 			pollingLock.notifyAll();
 		}
-		if(e != null) throw e;
 	}
 
 	public void run() {
@@ -76,7 +70,7 @@ class PollingRemovableDriveMonitor implements RemovableDriveMonitor, Runnable {
 				LOG.info("Interrupted while waiting to poll");
 			Thread.currentThread().interrupt();
 		} catch(IOException e) {
-			exception = e;
+			callback.exceptionThrown(e);
 		}
 	}
 }
diff --git a/components/net/sf/briar/plugins/file/RemovableDriveMonitor.java b/components/net/sf/briar/plugins/file/RemovableDriveMonitor.java
index caa223fc7a7f5a8c4962c323950089894449ff28..9baa030d342435a3a129fb0dad90c63bef1a641e 100644
--- a/components/net/sf/briar/plugins/file/RemovableDriveMonitor.java
+++ b/components/net/sf/briar/plugins/file/RemovableDriveMonitor.java
@@ -12,5 +12,7 @@ interface RemovableDriveMonitor {
 	interface Callback {
 
 		void driveInserted(File root);
+
+		void exceptionThrown(IOException e);
 	}
 }
diff --git a/components/net/sf/briar/plugins/file/RemovableDrivePlugin.java b/components/net/sf/briar/plugins/file/RemovableDrivePlugin.java
index ab8817fc4063bdf5483df7de4155819b0d7d2900..0fd61460f754a4c5f4ad486997cb74cf2bd6790d 100644
--- a/components/net/sf/briar/plugins/file/RemovableDrivePlugin.java
+++ b/components/net/sf/briar/plugins/file/RemovableDrivePlugin.java
@@ -123,4 +123,8 @@ implements RemovableDriveMonitor.Callback {
 			for(File f : files) if(f.isFile()) createReaderFromFile(f);
 		}
 	}
+
+	public void exceptionThrown(IOException e) {
+		if(LOG.isLoggable(Level.WARNING)) LOG.warning(e.toString());
+	}
 }
diff --git a/test/net/sf/briar/plugins/file/PollingRemovableDriveMonitorTest.java b/test/net/sf/briar/plugins/file/PollingRemovableDriveMonitorTest.java
index cc9e4f5dda14e65cbf525ef4c132740ef9099cf9..6d9230bffd335de93e923787667a5a127f0accab 100644
--- a/test/net/sf/briar/plugins/file/PollingRemovableDriveMonitorTest.java
+++ b/test/net/sf/briar/plugins/file/PollingRemovableDriveMonitorTest.java
@@ -3,90 +3,92 @@ package net.sf.briar.plugins.file;
 import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import net.sf.briar.BriarTestCase;
 import net.sf.briar.plugins.file.RemovableDriveMonitor.Callback;
 
-import org.jmock.Expectations;
-import org.jmock.Mockery;
 import org.junit.Test;
 
 public class PollingRemovableDriveMonitorTest extends BriarTestCase {
 
 	@Test
 	public void testOneCallbackPerFile() throws Exception {
+		// Create a finder that returns no files the first time, then two files
 		final File file1 = new File("foo");
 		final File file2 = new File("bar");
-		// Create a finder that returns no files the first time, then two files
-		final List<File> noDrives = Collections.emptyList();
-		final List<File> twoDrives = new ArrayList<File>();
-		twoDrives.add(file1);
-		twoDrives.add(file2);
-		Mockery context = new Mockery();
-		final RemovableDriveFinder finder =
-			context.mock(RemovableDriveFinder.class);
-		context.checking(new Expectations() {{
-			oneOf(finder).findRemovableDrives();
-			will(returnValue(noDrives));
-			oneOf(finder).findRemovableDrives();
-			will(returnValue(twoDrives));
-		}});
-		// Create a callback that will wait for two files before stopping
-		final List<File> detected = new ArrayList<File>();
+		final RemovableDriveFinder finder = new RemovableDriveFinder() {
+
+			private AtomicBoolean firstCall = new AtomicBoolean(true);
+
+			public Collection<File> findRemovableDrives() throws IOException {
+				if(firstCall.getAndSet(false)) return Collections.emptyList();
+				else return Arrays.asList(new File[] {file1, file2});
+			}
+		};
+		// Create a callback that waits for two files
 		final CountDownLatch latch = new CountDownLatch(2);
-		final Callback callback = new Callback() {
+		final List<File> detected = new ArrayList<File>();
+		Callback callback = new Callback() {
+
 			public void driveInserted(File f) {
 				detected.add(f);
 				latch.countDown();
 			}
+
+			public void exceptionThrown(IOException e) {
+				fail();
+			}
 		};
 		// Create the monitor and start it
 		final RemovableDriveMonitor monitor = new PollingRemovableDriveMonitor(
-				Executors.newCachedThreadPool(), finder, 10);
+				Executors.newCachedThreadPool(), finder, 1);
 		monitor.start(callback);
 		// Wait for the monitor to detect the files
-		assertTrue(latch.await(5, TimeUnit.SECONDS));
+		assertTrue(latch.await(10, TimeUnit.SECONDS));
 		monitor.stop();
 		// Check that both files were detected
 		assertEquals(2, detected.size());
 		assertTrue(detected.contains(file1));
 		assertTrue(detected.contains(file2));
-		// Check that the finder was polled twice
-		context.assertIsSatisfied();
 	}
 
 	@Test
-	public void testExceptionRethrownWhenStopping() throws Exception {
-		final List<File> noDrives = Collections.emptyList();
+	public void testExceptionCallback() throws Exception {
 		// Create a finder that throws an exception the second time it's polled
-		Mockery context = new Mockery();
-		final RemovableDriveFinder finder =
-			context.mock(RemovableDriveFinder.class);
-		context.checking(new Expectations() {{
-			oneOf(finder).findRemovableDrives();
-			will(returnValue(noDrives));
-			oneOf(finder).findRemovableDrives();
-			will(throwException(new IOException()));
-		}});
-		// Create the monitor, start it, and give it some time to run
-		final RemovableDriveMonitor monitor = new PollingRemovableDriveMonitor(
-				Executors.newCachedThreadPool(), finder, 10);
-		monitor.start(new Callback() {
+		final RemovableDriveFinder finder = new RemovableDriveFinder() {
+
+			private AtomicBoolean firstCall = new AtomicBoolean(true);
+
+			public Collection<File> findRemovableDrives() throws IOException {
+				if(firstCall.getAndSet(false)) return Collections.emptyList();
+				else throw new IOException();
+			}
+		};
+		// Create a callback that waits for an exception
+		final CountDownLatch latch = new CountDownLatch(1);
+		Callback callback = new Callback() {
+
 			public void driveInserted(File root) {
 				fail();
 			}
-		});
-		Thread.sleep(100);
-		// The monitor should rethrow the exception when it stops
-		try {
-			monitor.stop();
-			fail();
-		} catch(IOException expected) {}
-		context.assertIsSatisfied();
+
+			public void exceptionThrown(IOException e) {
+				latch.countDown();
+			}
+		};
+		// Create the monitor and start it
+		final RemovableDriveMonitor monitor = new PollingRemovableDriveMonitor(
+				Executors.newCachedThreadPool(), finder, 1);
+		monitor.start(callback);
+		assertTrue(latch.await(10, TimeUnit.SECONDS));
+		monitor.stop();
 	}
 }
diff --git a/test/net/sf/briar/plugins/file/UnixRemovableDriveMonitorTest.java b/test/net/sf/briar/plugins/file/UnixRemovableDriveMonitorTest.java
index ae3393a54824d04f4f70692133e3daf5e0a197cc..4e7af6079a29cd6bc4b81e0f5bcbeeaffb2f2130 100644
--- a/test/net/sf/briar/plugins/file/UnixRemovableDriveMonitorTest.java
+++ b/test/net/sf/briar/plugins/file/UnixRemovableDriveMonitorTest.java
@@ -1,6 +1,7 @@
 package net.sf.briar.plugins.file;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
@@ -33,9 +34,14 @@ public class UnixRemovableDriveMonitorTest extends BriarTestCase {
 		File doesNotExist = new File(testDir, "doesNotExist");
 		RemovableDriveMonitor monitor = createMonitor(doesNotExist);
 		monitor.start(new Callback() {
+
 			public void driveInserted(File root) {
 				fail();
 			}
+
+			public void exceptionThrown(IOException e) {
+				fail();
+			}
 		});
 		monitor.stop();
 	}
@@ -50,10 +56,15 @@ public class UnixRemovableDriveMonitorTest extends BriarTestCase {
 		final List<File> detected = new ArrayList<File>();
 		final CountDownLatch latch = new CountDownLatch(2);
 		final Callback callback = new Callback() {
+
 			public void driveInserted(File f) {
 				detected.add(f);
 				latch.countDown();
 			}
+
+			public void exceptionThrown(IOException e) {
+				fail();
+			}
 		};
 		// Create the monitor and start it
 		RemovableDriveMonitor monitor = createMonitor(testDir);