diff -u smack-dev-1.4.1/source/org/jivesoftware/smack/PacketReader.java smack-dev-1.4.1/source/org/jivesoftware/smack/PacketReader.java
--- smack-dev-1.4.1/source/org/jivesoftware/smack/PacketReader.java	2004-12-24 19:15:21.000000000 -0500
+++ smack-dev-1.4.1/source/org/jivesoftware/smack/PacketReader.java	2004-12-24 23:07:05.000000000 -0500
@@ -76,7 +76,9 @@
 
         listenerThread = new Thread() {
             public void run() {
-                processListeners();
+                try {
+					processListeners();
+				} catch (InterruptedException e) {}
             }
         };
         listenerThread.setName("Smack Listener Processor");
@@ -165,7 +167,7 @@
         }
     }
 
-    /**
+	/**
      * Shuts the packet reader down.
      */
     public void shutdown() {
@@ -182,6 +184,7 @@
             }
         }
         done = true;
+        interruptThreads();
     }
 
     /**
@@ -194,10 +197,7 @@
         done = true;
         connection.close();
 
-        // Wake up the conditional wait in startup, if it's still running.
-        synchronized(connectionIDLock) {
-            connectionIDLock.notifyAll();
-        }
+        interruptThreads();
 
         // Notify connection listeners of the error.
         ArrayList listenersCopy;
@@ -211,10 +211,32 @@
         }
     }
 
+    protected void interruptThreads() {
+    	listenerThread.interrupt();
+    	readerThread.interrupt();
+
+    	/*
+    	 * Wait 100 ms for each thread to clean-up, then return.
+    	 */
+
+    	try {
+			listenerThread.join(100);
+		} catch (InterruptedException e) {
+			Thread.currentThread().interrupt();
+		}
+
+    	try {
+			readerThread.join(100);
+		} catch (InterruptedException e) {
+			Thread.currentThread().interrupt();
+		}
+    }
+
     /**
      * Process listeners.
+     * @throws InterruptedException If the listeners thread is interrupted.
      */
-    private void processListeners() {
+    private void processListeners() throws InterruptedException {
         boolean processedPacket = false;
         while (!done) {
             synchronized (listeners) {
@@ -235,10 +257,7 @@
                 }
             }
             if (!processedPacket) {
-                try {
-                    Thread.sleep(100);
-                }
-                catch (InterruptedException ie) { }
+            	Thread.sleep(100);
             }
         }
     }
@@ -293,6 +312,8 @@
                         connection.close();
                     }
                 }
+                if (Thread.interrupted())
+                	throw new InterruptedException();
                 eventType = parser.next();
             } while (!done && eventType != XmlPullParser.END_DOCUMENT);
         }
only in patch2:
unchanged:
--- smack-dev-1.4.1.orig/source/org/jivesoftware/smack/PacketCollector.java	2004-12-24 18:29:06.000000000 -0500
+++ smack-dev-1.4.1/source/org/jivesoftware/smack/PacketCollector.java	2004-12-24 22:13:10.000000000 -0500
@@ -121,6 +121,9 @@
     /**
      * Returns the next available packet. The method call will block (not return)
      * until a packet is available.
+     * 
+     * <p>The thread's interrupted flag will be set if the thread is
+     * interrupted while blocking in this method.</p>
      *
      * @return the next available packet.
      */
@@ -130,7 +133,9 @@
             try {
                 wait();
             }
-            catch (InterruptedException ie) { }
+            catch (InterruptedException ie) {
+            	Thread.currentThread().interrupt();
+           	}
         }
         return (Packet)resultQueue.removeLast();
     }
@@ -139,6 +144,9 @@
      * Returns the next available packet. The method call will block (not return)
      * until a packet is available or the <tt>timeout</tt> has elapased. If the
      * timeout elapses without a result, <tt>null</tt> will be returned.
+     * 
+     * <p>The thread's interrupted flag will be set if the thread is
+     * interrupted while blocking in this method.</p>
      *
      * @param timeout the amount of time to wait for the next packet (in milleseconds).
      * @return the next available packet.
@@ -149,7 +157,9 @@
             try {
                 wait(timeout);
             }
-            catch (InterruptedException ie) { }
+            catch (InterruptedException ie) {
+            	Thread.currentThread().interrupt();
+            }
         }
         // If still no result, return null.
         if (resultQueue.isEmpty()) {
only in patch2:
unchanged:
--- smack-dev-1.4.1.orig/source/org/jivesoftware/smack/PacketWriter.java	2004-12-24 18:29:06.000000000 -0500
+++ smack-dev-1.4.1/source/org/jivesoftware/smack/PacketWriter.java	2004-12-24 22:16:41.000000000 -0500
@@ -43,6 +43,7 @@
     private boolean listenersDeleted = false;
     private Thread listenerThread;
     private LinkedList sentPackets = new LinkedList();
+    private Thread keepAliveThread;
 
     /**
      * Creates a new packet writer with the specified connection.
@@ -56,7 +57,9 @@
 
         writerThread = new Thread() {
             public void run() {
-                writePackets();
+                try {
+					writePackets();
+				} catch (InterruptedException e) {}
             }
         };
         writerThread.setName("Smack Packet Writer");
@@ -64,7 +67,9 @@
 
         listenerThread = new Thread() {
             public void run() {
-                processListeners();
+                try {
+					processListeners();
+				} catch (InterruptedException e) {	}
             }
         };
         listenerThread.setName("Smack Writer Listener Processor");
@@ -74,7 +79,8 @@
         // out a space character each time it runs to keep the TCP/IP connection open.
         int keepAliveInterval = SmackConfiguration.getKeepAliveInterval();
         if (keepAliveInterval > 0) {
-            Thread keepAliveThread = new Thread(new KeepAliveTask(keepAliveInterval));
+            keepAliveThread = new Thread(new KeepAliveTask(keepAliveInterval));
+			keepAliveThread.setName("Smack KeepAlive Task");
             keepAliveThread.setDaemon(true);
             keepAliveThread.start();
         }
@@ -160,20 +166,51 @@
      */
     public void shutdown() {
         done = true;
+        interruptThreads();
+    }
+
+    protected void interruptThreads() {
+    	listenerThread.interrupt();
+    	writerThread.interrupt();
+    	if (null != keepAliveThread) {
+    		keepAliveThread.interrupt();
+    	}
+
+    	/*
+    	 * Wait 100 ms for each thread to clean-up, then return.
+    	 */
+
+    	try {
+			listenerThread.join(100);
+		} catch (InterruptedException e) {
+			Thread.currentThread().interrupt();
+		}
+
+    	try {
+			writerThread.join(100);
+		} catch (InterruptedException e) {
+			Thread.currentThread().interrupt();
+		}
+
+		if (null != keepAliveThread) {
+			try {
+				keepAliveThread.join(100);
+			} catch (InterruptedException e) {
+				Thread.currentThread().interrupt();
+			}
+		}
     }
 
     /**
      * Returns the next available packet from the queue for writing.
      *
      * @return the next packet for writing.
+     * @throws InterruptedException If the thread was interrupted.
      */
-    private Packet nextPacket() {
+    private Packet nextPacket() throws InterruptedException {
         synchronized(queue) {
             while (!done && queue.size() == 0) {
-                try {
-                    queue.wait(2000);
-                }
-                catch (InterruptedException ie) { }
+            	queue.wait();
             }
             if (queue.size() > 0) {
                 return (Packet)queue.removeLast();
@@ -184,7 +221,7 @@
         }
     }
 
-    private void writePackets() {
+    private void writePackets() throws InterruptedException {
         try {
             // Open the stream.
             StringBuffer stream = new StringBuffer();
@@ -221,6 +258,7 @@
         catch (IOException ioe){
             if (!done) {
                 done = true;
+                interruptThreads();
                 connection.packetReader.notifyConnectionError(ioe);
             }
         }
@@ -228,17 +266,15 @@
 
     /**
      * Process listeners.
+     * @throws InterruptedException If the listeners thread was interrupted.
      */
-    private void processListeners() {
+    private void processListeners() throws InterruptedException {
         while (!done) {
             Packet sentPacket;
             // Wait until a new packet has been sent
             synchronized (sentPackets) {
                 while (!done && sentPackets.size() == 0) {
-                    try {
-                        sentPackets.wait(2000);
-                    }
-                    catch (InterruptedException ie) { }
+                	sentPackets.wait();
                 }
                 if (sentPackets.size() > 0) {
                     sentPacket = (Packet)sentPackets.removeLast();
@@ -333,7 +369,9 @@
                     // Sleep until we should write the next keep-alive.
                     Thread.sleep(delay);
                 }
-                catch (InterruptedException ie) { }
+                catch (InterruptedException ie) {
+                	break;
+                }
             }
         }
     }
only in patch2:
unchanged:
--- smack-dev-1.4.1.orig/source/org/jivesoftware/smack/XMPPConnection.java	2004-12-24 18:29:06.000000000 -0500
+++ smack-dev-1.4.1/source/org/jivesoftware/smack/XMPPConnection.java	2004-12-24 23:05:39.000000000 -0500
@@ -429,7 +429,9 @@
             try {
                 Thread.sleep(500);
             }
-            catch (Exception e) {
+            catch (InterruptedException e) {
+            	Thread.currentThread().interrupt();
+            	return null;
             }
             elapsed += 500;
         }
@@ -526,9 +528,13 @@
         packetWriter.sendPacket(new Presence(Presence.Type.UNAVAILABLE));
         packetReader.shutdown();
         packetWriter.shutdown();
-        // Wait 150 ms for processes to clean-up, then shutdown.
+
+        /*
+         * Close the socket first to avoid reader.close from blocking
+         * if another thread is blocked on a read operation.
+         */
         try {
-            Thread.sleep(150);
+            socket.close();
         }
         catch (Exception e) {
         }
@@ -545,12 +551,7 @@
 			writer = null;
 		}
 
-        try {
-            socket.close();
-        }
-        catch (Exception e) {
-        }
-        authenticated = false;
+		authenticated = false;
         connected = false;
     }
 
