diff --git a/apps/sam/java/src/net/i2p/sam/client/SAMReader.java b/apps/sam/java/src/net/i2p/sam/client/SAMReader.java
index d25d1f0537f4ab25d266b276c47023d0b23bbbb6..bc8d989581571d2cb050e445c473cb5e4d2e3db1 100644
--- a/apps/sam/java/src/net/i2p/sam/client/SAMReader.java
+++ b/apps/sam/java/src/net/i2p/sam/client/SAMReader.java
@@ -20,6 +20,7 @@ public class SAMReader {
     private final InputStream _inRaw;
     private final SAMClientEventListener _listener;
     private volatile boolean _live;
+    private Thread _thread;
     
     public SAMReader(I2PAppContext context, InputStream samIn, SAMClientEventListener listener) {
         _log = context.logManager().getLog(SAMReader.class);
@@ -27,13 +28,22 @@ public class SAMReader {
         _listener = listener;
     }
     
-    public void startReading() {
+    public synchronized void startReading() {
+        if (_live)
+            throw new IllegalStateException();
         _live = true;
         I2PAppThread t = new I2PAppThread(new Runner(), "SAM reader");
         t.start();
+        _thread = t;
     }
 
-    public void stopReading() { _live = false; }
+    public synchronized void stopReading() {
+        _live = false;
+        if (_thread != null) {
+            _thread.interrupt();
+            _thread = null;
+        }
+    }
     
     /**
      * Async event notification interface for SAM clients
@@ -89,10 +99,11 @@ public class SAMReader {
                     }
                     if (c == -1) {
                         _log.error("Error reading from the SAM bridge");
-                        return;
+                        break;
                     }
                 } catch (IOException ioe) {
                     _log.error("Error reading from SAM", ioe);
+                    break;
                 }
                 
                 String line = new String(baos.toByteArray());
@@ -103,14 +114,15 @@ public class SAMReader {
                     break;
                 }
                 
-                _log.debug("Line read from the bridge: " + line);
+                if (_log.shouldDebug())
+                    _log.debug("Line read from the bridge: " + line);
                 
                 StringTokenizer tok = new StringTokenizer(line);
                 
                 if (tok.countTokens() < 2) {
                     _log.error("Invalid SAM line: [" + line + "]");
                     _live = false;
-                    return;
+                    break;
                 }
                 
                 String major = tok.nextToken();
@@ -133,6 +145,8 @@ public class SAMReader {
                 
                 processEvent(major, minor, params);
             }
+            if (_log.shouldWarn())
+                _log.warn("SAMReader exiting");
         }
     }
     
diff --git a/apps/sam/java/src/net/i2p/sam/client/SAMStreamSend.java b/apps/sam/java/src/net/i2p/sam/client/SAMStreamSend.java
index 29e040394dbe74a1b4ddd2e7c0d56082c5a77132..4e034dfa578784a41bdccd16ec90af3045d77791 100644
--- a/apps/sam/java/src/net/i2p/sam/client/SAMStreamSend.java
+++ b/apps/sam/java/src/net/i2p/sam/client/SAMStreamSend.java
@@ -263,6 +263,11 @@ public class SAMStreamSend {
             }
             
             closed();
+            if (_log.shouldLog(Log.DEBUG))
+                _log.debug("Runner exiting");
+            // stop the reader, since we're only doing this once for testing
+            // you wouldn't do this in a real application
+            _reader.stopReading();
         }
     }
 }