Index: core/src/main/java/hudson/model/Run.java
===================================================================
--- core/src/main/java/hudson/model/Run.java	(revision 16755)
+++ core/src/main/java/hudson/model/Run.java	(working copy)
@@ -78,7 +78,7 @@
 import java.util.Map;
 import java.util.logging.Level;
 import java.util.logging.Logger;
-import java.util.zip.GZIPInputStream;
+import com.sun.bugs.id4691425.MultiMemberGZIPInputStream;
 
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletResponse;
@@ -758,7 +758,7 @@
     	File compressedLogFile = new File(logFile.getParentFile(), logFile.getName()+ ".gz");
     	if (compressedLogFile.exists()) {
     		return new InputStreamReader(
-    				new GZIPInputStream(
+    				new MultiMemberGZIPInputStream(
     						new FileInputStream(compressedLogFile)));
     	} 
     	
Index: core/src/main/java/hudson/FilePath.java
===================================================================
--- core/src/main/java/hudson/FilePath.java	(revision 16755)
+++ core/src/main/java/hudson/FilePath.java	(working copy)
@@ -83,7 +83,7 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.zip.GZIPOutputStream;
-import java.util.zip.GZIPInputStream;
+import com.sun.bugs.id4691425.MultiMemberGZIPInputStream;
 import java.util.zip.ZipInputStream;
 
 /**
@@ -422,7 +422,7 @@
             public InputStream extract(InputStream _in) throws IOException {
                 HeadBufferingStream in = new HeadBufferingStream(_in,SIDE_BUFFER_SIZE);
                 try {
-                    return new GZIPInputStream(in);
+                    return new MultiMemberGZIPInputStream(in);
                 } catch (IOException e) {
                     // various people reported "java.io.IOException: Not in GZIP format" here, so diagnose this problem better
                     in.fillSide();
@@ -1077,7 +1077,7 @@
             Future<Void> future = target.actAsync(new FileCallable<Void>() {
                 public Void invoke(File f, VirtualChannel channel) throws IOException {
                     try {
-                        readFromTar(remote+'/'+fileMask, f,new GZIPInputStream(pipe.getIn()));
+                        readFromTar(remote+'/'+fileMask, f,new MultiMemberGZIPInputStream(pipe.getIn()));
                         return null;
                     } finally {
                         pipe.getIn().close();
@@ -1105,7 +1105,7 @@
                 }
             });
             try {
-                readFromTar(remote+'/'+fileMask,new File(target.remote),new GZIPInputStream(pipe.getIn()));
+                readFromTar(remote+'/'+fileMask,new File(target.remote),new MultiMemberGZIPInputStream(pipe.getIn()));
             } catch (IOException e) {// BuildException or IOException
                 try {
                     future.get(3,TimeUnit.SECONDS);
Index: core/src/main/java/hudson/util/CompressedFile.java
===================================================================
--- core/src/main/java/hudson/util/CompressedFile.java	(revision 16755)
+++ core/src/main/java/hudson/util/CompressedFile.java	(working copy)
@@ -40,7 +40,7 @@
 import java.util.concurrent.TimeUnit;
 import java.util.logging.Level;
 import java.util.logging.Logger;
-import java.util.zip.GZIPInputStream;
+import com.sun.bugs.id4691425.MultiMemberGZIPInputStream;
 import java.util.zip.GZIPOutputStream;
 
 /**
@@ -93,7 +93,7 @@
 
         // check if the compressed file exists
         if(gz.exists())
-            return new GZIPInputStream(new FileInputStream(gz));
+            return new MultiMemberGZIPInputStream(new FileInputStream(gz));
 
         // no such file
         throw new FileNotFoundException(file.getName());
Index: core/src/main/java/com/sun/bugs/id4691425/MultiMemberGZIPInputStream.java
===================================================================
--- core/src/main/java/com/sun/bugs/id4691425/MultiMemberGZIPInputStream.java	(revision 0)
+++ core/src/main/java/com/sun/bugs/id4691425/MultiMemberGZIPInputStream.java	(revision 0)
@@ -0,0 +1,99 @@
+package com.sun.bugs.id4691425;
+
+import java.io.InputStream;
+import java.io.PushbackInputStream;
+import java.io.IOException;
+import java.util.zip.GZIPInputStream;
+
+/**
+ * This is a workaround for http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4691425
+ */
+public class MultiMemberGZIPInputStream extends GZIPInputStream {
+
+    public MultiMemberGZIPInputStream(InputStream in, int size) throws IOException
+    {
+        // Wrap the stream in a PushbackInputStream...
+        super(new PushbackInputStream(in, size), size);
+        this.size=size;
+    }
+
+    public MultiMemberGZIPInputStream(InputStream in) throws IOException
+    {
+        // Wrap the stream in a PushbackInputStream...
+        super(new PushbackInputStream(in, 1024));
+        this.size=-1;
+    }
+
+    private MultiMemberGZIPInputStream(MultiMemberGZIPInputStream parent) throws IOException
+    {
+        super(parent.in);
+        this.size=-1;
+        this.parent=parent.parent==null ? parent : parent.parent;
+        this.parent.child=this;
+    }
+
+    private MultiMemberGZIPInputStream(MultiMemberGZIPInputStream parent, int size) throws IOException
+    {
+        super(parent.in, size);
+        this.size=size;
+        this.parent=parent.parent==null ? parent : parent.parent;
+        this.parent.child=this;
+    }
+
+    private MultiMemberGZIPInputStream parent;
+    private MultiMemberGZIPInputStream child;
+    private int size;
+    private boolean eos;
+
+    public int read(byte[] inputBuffer, int inputBufferOffset, int inputBufferLen) throws IOException {
+
+        if (eos) { return -1;}
+        if (this.child!=null)
+            return this.child.read(inputBuffer, inputBufferOffset, inputBufferLen);
+
+        int charsRead=super.read(inputBuffer, inputBufferOffset, inputBufferLen);
+        if (charsRead==-1)
+        {
+            // Push any remaining buffered data back onto the stream
+            // If the stream is then not empty, use it to construct
+            // a new instance of this class and delegate this and any
+            // future calls to it...
+            int n = inf.getRemaining() - 8;
+            if (n > 0)
+            {
+                // More than 8 bytes remaining in deflater
+                // First 8 are gzip trailer. Add the rest to
+                // any un-read data...
+                ((PushbackInputStream)this.in).unread(buf, len-n, n);
+            }
+            else
+            {
+                // Nothing in the buffer. We need to know whether or not
+                // there is unread data available in the underlying stream
+                // since the base class will not handle an empty file.
+                // Read a byte to see if there is data and if so,
+                // push it back onto the stream...
+                byte[] b=new byte[1];
+                int ret=in.read(b,0,1);
+                if (ret==-1)
+                {
+                    eos=true;
+                    return -1;
+                }
+                else
+                    ((PushbackInputStream)this.in).unread(b, 0, 1);
+            }
+
+            MultiMemberGZIPInputStream child;
+            if (this.size==-1)
+                child=new MultiMemberGZIPInputStream(this);
+            else
+                child=new MultiMemberGZIPInputStream(this, this.size);
+            return child.read(inputBuffer, inputBufferOffset, inputBufferLen);
+        }
+        else
+            return charsRead;
+    }
+
+}
+