diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java
index d73e2055a50aed3cf5626094f970e1fa9e4c5f70..8df3ea5b2be47188570a1f4f3c1b9eec2155f414 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java
@@ -232,7 +232,7 @@ public void close() throws IOException {
 	class SshFetchConnection extends BasePackFetchConnection {
 		private ChannelExec channel;
 
-		private Thread errorThread;
+		private StreamCopyThread errorThread;
 
 		private int exitStatus;
 
@@ -275,7 +275,7 @@ public void close() {
 
 			if (errorThread != null) {
 				try {
-					errorThread.join();
+					errorThread.halt();
 				} catch (InterruptedException e) {
 					// Stop waiting and return anyway.
 				} finally {
@@ -300,7 +300,7 @@ public void close() {
 	class SshPushConnection extends BasePackPushConnection {
 		private ChannelExec channel;
 
-		private Thread errorThread;
+		private StreamCopyThread errorThread;
 
 		private int exitStatus;
 
@@ -343,7 +343,7 @@ public void close() {
 
 			if (errorThread != null) {
 				try {
-					errorThread.join();
+					errorThread.halt();
 				} catch (InterruptedException e) {
 					// Stop waiting and return anyway.
 				} finally {
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/StreamCopyThread.java b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/StreamCopyThread.java
index c36835692ddd11b018e6a6ea0e7ed4d5519101a1..f2715aca2b46fed453cb1d05626223ab6ef9453d 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/util/io/StreamCopyThread.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/util/io/StreamCopyThread.java
@@ -59,6 +59,8 @@ public class StreamCopyThread extends Thread {
 
 	private final AtomicInteger flushCounter = new AtomicInteger(0);
 
+	private volatile boolean done;
+
 	/**
 	 * Create a thread to copy data from an input stream to an output stream.
 	 *
@@ -87,6 +89,26 @@ public void flush() {
 		interrupt();
 	}
 
+	/**
+	 * Request that the thread terminate, and wait for it.
+	 * <p>
+	 * This method signals to the copy thread that it should stop as soon as
+	 * there is no more IO occurring.
+	 *
+	 * @throws InterruptedException
+	 *             the calling thread was interrupted.
+	 */
+	public void halt() throws InterruptedException {
+		for (;;) {
+			join(250 /* milliseconds */);
+			if (isAlive()) {
+				done = true;
+				interrupt();
+			} else
+				break;
+		}
+	}
+
 	@Override
 	public void run() {
 		try {
@@ -96,6 +118,9 @@ public void run() {
 					if (needFlush())
 						dst.flush();
 
+					if (done)
+						break;
+
 					final int n;
 					try {
 						n = src.read(buf);