diff --git a/briar-core/src/net/sf/briar/plugins/modem/ReliabilityLayer.java b/briar-core/src/net/sf/briar/plugins/modem/ReliabilityLayer.java
index edf67ac576edf81f7afba4c7ff477367c148abfb..d033aa678aeeb8f68d48faa1027c7684784b68e3 100644
--- a/briar-core/src/net/sf/briar/plugins/modem/ReliabilityLayer.java
+++ b/briar-core/src/net/sf/briar/plugins/modem/ReliabilityLayer.java
@@ -1,5 +1,6 @@
 package net.sf.briar.plugins.modem;
 
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.logging.Level.WARNING;
 
 import java.io.IOException;
@@ -11,6 +12,8 @@ import java.util.logging.Logger;
 
 class ReliabilityLayer implements ReadHandler, WriteHandler {
 
+	private static final int TICK_INTERVAL = 500; // Milliseconds
+
 	private static final Logger LOG =
 			Logger.getLogger(ReliabilityLayer.class.getName());
 
@@ -31,7 +34,7 @@ class ReliabilityLayer implements ReadHandler, WriteHandler {
 
 	void start() {
 		SlipEncoder encoder = new SlipEncoder(this);
-		Sender sender = new Sender(encoder);
+		final Sender sender = new Sender(encoder);
 		receiver = new Receiver(sender);
 		decoder = new SlipDecoder(receiver);
 		inputStream = new ReceiverInputStream(receiver);
@@ -39,11 +42,22 @@ class ReliabilityLayer implements ReadHandler, WriteHandler {
 		writer = new Thread("ReliabilityLayer") {
 			@Override
 			public void run() {
+				long now = System.currentTimeMillis();
+				long next = now + TICK_INTERVAL;
 				try {
 					while(running) {
-						byte[] b = writes.take();
-						if(b.length == 0) return; // Poison pill
-						writeHandler.handleWrite(b);
+						byte[] b = null;
+						while(now < next && b == null) {
+							b = writes.poll(next - now, MILLISECONDS);
+							now = System.currentTimeMillis();
+						}
+						if(b == null) {
+							sender.tick();
+							while(next <= now) next += TICK_INTERVAL;
+						} else {
+							if(b.length == 0) return; // Poison pill
+							writeHandler.handleWrite(b);
+						}
 					}
 				} catch(InterruptedException e) {
 					if(LOG.isLoggable(WARNING))
@@ -52,7 +66,7 @@ class ReliabilityLayer implements ReadHandler, WriteHandler {
 					running = false;
 				} catch(IOException e) {
 					if(LOG.isLoggable(WARNING))
-						LOG.warning("Interrupted while writing");
+						LOG.log(WARNING, e.toString(), e);
 					running = false;
 				}
 			}
@@ -70,7 +84,6 @@ class ReliabilityLayer implements ReadHandler, WriteHandler {
 	}
 
 	void stop() {
-		if(!running) throw new IllegalStateException();
 		running = false;
 		receiver.invalidate();
 		writes.add(new byte[0]); // Poison pill
diff --git a/briar-core/src/net/sf/briar/plugins/modem/Sender.java b/briar-core/src/net/sf/briar/plugins/modem/Sender.java
index 3bf2c75f5bd8095ef54b34d8598e0c9bc1fa4407..bb2ad8a7bb4b4d676e2a3ea5b7b4a22f40b3bf32 100644
--- a/briar-core/src/net/sf/briar/plugins/modem/Sender.java
+++ b/briar-core/src/net/sf/briar/plugins/modem/Sender.java
@@ -1,19 +1,13 @@
 package net.sf.briar.plugins.modem;
 
-import static java.util.logging.Level.WARNING;
-
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.logging.Logger;
 
 class Sender {
 
-	private static final Logger LOG =
-			Logger.getLogger(Sender.class.getName());
-
 	// All times are in milliseconds
 	private static final int MIN_TIMEOUT = 1000;
 	private static final int MAX_TIMEOUT = 60 * 1000;
@@ -99,7 +93,7 @@ class Sender {
 			writeHandler.handleWrite(fastRetransmit.data.getBuffer());
 	}
 
-	void tick() {
+	void tick() throws IOException {
 		long now = System.currentTimeMillis();
 		List<Outstanding> retransmit = null;
 		boolean sendProbe = false;
@@ -132,23 +126,17 @@ class Sender {
 				}
 			}
 		}
-		try {
-			// Send a window probe if necessary
-			if(sendProbe) {
-				byte[] buf = new byte[Data.MIN_LENGTH];
-				Data probe = new Data(buf);
-				probe.setChecksum(probe.calculateChecksum());
-				writeHandler.handleWrite(buf);
-			}
-			// Retransmit any lost data frames
-			if(retransmit != null) {
-				for(Outstanding o : retransmit)
-					writeHandler.handleWrite(o.data.getBuffer());
-			}
-		} catch(IOException e) {
-			// FIXME: Do something more meaningful
-			if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e);
-			return;
+		// Send a window probe if necessary
+		if(sendProbe) {
+			byte[] buf = new byte[Data.MIN_LENGTH];
+			Data probe = new Data(buf);
+			probe.setChecksum(probe.calculateChecksum());
+			writeHandler.handleWrite(buf);
+		}
+		// Retransmit any lost data frames
+		if(retransmit != null) {
+			for(Outstanding o : retransmit)
+				writeHandler.handleWrite(o.data.getBuffer());
 		}
 	}