+ Fixed a race condition in the remote data transfer that results in silent file copy failures.
+ (issue 7871)
Maven Plugin : Successful build ends with NPE
(issue 8436)
diff --git a/core/src/main/java/hudson/FilePath.java b/core/src/main/java/hudson/FilePath.java
index 84184eaeff..8b84f09000 100644
--- a/core/src/main/java/hudson/FilePath.java
+++ b/core/src/main/java/hudson/FilePath.java
@@ -1405,6 +1405,10 @@ public final class FilePath implements Serializable {
}
}
});
+
+ // make sure the write fully happens before we return.
+ if (channel!=null)
+ channel.syncLocalIO();
}
/**
diff --git a/core/src/test/java/hudson/FilePathTest.java b/core/src/test/java/hudson/FilePathTest.java
index 4dfdd8eff5..df82a2403b 100644
--- a/core/src/test/java/hudson/FilePathTest.java
+++ b/core/src/test/java/hudson/FilePathTest.java
@@ -23,12 +23,24 @@
*/
package hudson;
+import hudson.remoting.Future;
import hudson.remoting.VirtualChannel;
+import hudson.util.IOException2;
import hudson.util.NullStream;
import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import org.apache.commons.io.output.CountingOutputStream;
import org.apache.commons.io.output.NullOutputStream;
+import org.jvnet.hudson.test.Bug;
/**
* @author Kohsuke Kawaguchi
@@ -61,6 +73,89 @@ public class FilePathTest extends ChannelTestCase {
}
}
+ /**
+ * As we moved the I/O handling to another thread, there's a race condition in
+ * {@link FilePath#copyTo(OutputStream)} — this method can return before
+ * all the writes are delivered to {@link OutputStream}.
+ *
+ *
+ * To reproduce that problem, we use a large number of threads, so that we can
+ * maximize the chance of out-of-order execution, and make sure we are
+ * seeing the right byte count at the end.
+ *
+ * Also see JENKINS-7897
+ */
+ @Bug(7871)
+ public void testCopyTo3() throws Exception {
+ final File tmp = File.createTempFile("testCopyTo3","");
+
+ FileOutputStream os = new FileOutputStream(tmp);
+ final int size = 90000;
+ byte[] buf = new byte[size];
+ for (int i=0; i r = new ArrayList();
+ for (int i=0; i<100; i++) {
+ r.add(es.submit(new Callable