diff options
author | Shawn O. Pearce <spearce@spearce.org> | 2010-05-15 17:01:49 -0700 |
---|---|---|
committer | Shawn O. Pearce <spearce@spearce.org> | 2010-05-19 11:43:42 -0700 |
commit | 2e961989e42b1fe7e8bd9eaa7a3d2e88a0d1d001 (patch) | |
tree | 97d8b4f2f80706f0edc3192dc8eefb4e51abe7c3 /org.eclipse.jgit | |
parent | b3247ba5244d95e0d2c850a3fa1f69668a5790f5 (diff) | |
download | jgit-2e961989e42b1fe7e8bd9eaa7a3d2e88a0d1d001.tar.gz jgit-2e961989e42b1fe7e8bd9eaa7a3d2e88a0d1d001.zip |
Fix SSH deadlock during OutOfMemoryError
In close() method of SshFetchConnection and SshPushConnection
errorThread.join() can wait forever if JSch will not close the
channel's error stream. Join with a timeout, and interrupt the
copy thread if its blocked on data that will never arrive.
Bug: 312863
Change-Id: I763081267653153eed9cd7763a015059338c2df8
Reported-by: Dmitry Neverov <dmitry.neverov@gmail.com>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Diffstat (limited to 'org.eclipse.jgit')
-rw-r--r-- | org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java | 8 | ||||
-rw-r--r-- | org.eclipse.jgit/src/org/eclipse/jgit/util/io/StreamCopyThread.java | 25 |
2 files changed, 29 insertions, 4 deletions
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 d73e2055a5..8df3ea5b2b 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 class TransportGitSsh extends SshTransport implements PackTransport { class SshFetchConnection extends BasePackFetchConnection { private ChannelExec channel; - private Thread errorThread; + private StreamCopyThread errorThread; private int exitStatus; @@ -275,7 +275,7 @@ public class TransportGitSsh extends SshTransport implements PackTransport { if (errorThread != null) { try { - errorThread.join(); + errorThread.halt(); } catch (InterruptedException e) { // Stop waiting and return anyway. } finally { @@ -300,7 +300,7 @@ public class TransportGitSsh extends SshTransport implements PackTransport { class SshPushConnection extends BasePackPushConnection { private ChannelExec channel; - private Thread errorThread; + private StreamCopyThread errorThread; private int exitStatus; @@ -343,7 +343,7 @@ public class TransportGitSsh extends SshTransport implements PackTransport { 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 c36835692d..f2715aca2b 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 class StreamCopyThread extends Thread { 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 class StreamCopyThread extends Thread { if (needFlush()) dst.flush(); + if (done) + break; + final int n; try { n = src.read(buf); |