Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn O. Pearce2010-03-20 22:33:26 +0000
committerShawn O. Pearce2010-03-21 02:18:14 +0000
commit0dc93a2f4ab0c9ef8293c825c393fe0bad8b110a (patch)
tree9ab792c14c2bf589e376e3b0dad675dd55e6fa2f
parent7182fbc422571e014e6b565db373ca9452229d14 (diff)
downloadjgit-0dc93a2f4ab0c9ef8293c825c393fe0bad8b110a.tar.gz
jgit-0dc93a2f4ab0c9ef8293c825c393fe0bad8b110a.tar.xz
jgit-0dc93a2f4ab0c9ef8293c825c393fe0bad8b110a.zip
Fix EGit deadlock listing branches of SSH remote
When listing branches, EGit only reads the advertisement and then disconnects. When it closes down the pack channel the remote side is waiting for the client to send our list of commands, or a flush-pkt to let it know there is nothing to do. However if an error thread is open watching the SSH stderr stream, we ask for it to finish before we send the flush-pkt. Unfortunately the thread won't terminate until the main output stream closes, which is waiting for the flush-pkt. A classic network deadlock. If the output stream needs a flush-pkt we send it before we wait for the error stream to close. If the flush-pkt is rejected, we close down the output stream early, assuming that the remote side is broken and we will get error information soon. Change-Id: I8d078a339077756220c113f49d206b1bf295d434 Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackConnection.java23
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java4
2 files changed, 26 insertions, 1 deletions
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackConnection.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackConnection.java
index a2c572c601..7b6d3e121a 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackConnection.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/BasePackConnection.java
@@ -282,8 +282,10 @@ abstract class BasePackConnection extends BaseConnection {
public void close() {
if (out != null) {
try {
- if (outNeedsEnd)
+ if (outNeedsEnd) {
+ outNeedsEnd = false;
pckOut.end();
+ }
out.close();
} catch (IOException err) {
// Ignore any close errors.
@@ -314,4 +316,23 @@ abstract class BasePackConnection extends BaseConnection {
}
}
}
+
+ /** Tell the peer we are disconnecting, if it cares to know. */
+ protected void endOut() {
+ if (outNeedsEnd && out != null) {
+ try {
+ outNeedsEnd = false;
+ pckOut.end();
+ } catch (IOException e) {
+ try {
+ out.close();
+ } catch (IOException err) {
+ // Ignore any close errors.
+ } finally {
+ out = null;
+ pckOut = null;
+ }
+ }
+ }
+ }
}
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 d4d4f5412f..fb2038b862 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/TransportGitSsh.java
@@ -264,6 +264,8 @@ public class TransportGitSsh extends SshTransport implements PackTransport {
@Override
public void close() {
+ endOut();
+
if (errorThread != null) {
try {
errorThread.join();
@@ -331,6 +333,8 @@ public class TransportGitSsh extends SshTransport implements PackTransport {
@Override
public void close() {
+ endOut();
+
if (errorThread != null) {
try {
errorThread.join();

Back to the top