Skip to content

Commit dcbdbcc

Browse files
committed
[CLOUDBEES-2018] fixing the root cause.
At some point after this code was originally written, I/O in remoting became asynchronous. So we need to sync with that before we swap out the new log output stream, or else you cut off stuff at the wrong moment. Normally the command transfer in remoting is slow enough that you get more or less synchronized output anyway, which is why this poblem remained unnoticed. But if the uncliamed buffer gets large, write operation will take a long time, which makes this issue more likely to show up. This fix address this problem by doing a proper sync. The recycling of ByteArrayOutputStream is also disabled because it makes synchronization tricky.
1 parent 982946b commit dcbdbcc

File tree

3 files changed

+25
-5
lines changed

3 files changed

+25
-5
lines changed

changelog.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@
5757
<ul class=image>
5858
<li class=rfe>
5959
Update center UI improvement. "Install" button is now always visisble.
60+
<li class=bug>
61+
Fixed a bug where a large output from Maven can cause module log output to go out of sync with module build log files.
6062
<li class=bug>
6163
Fixed prematurely re-drawn matrix test result graph.
6264
</ul>

maven-plugin/src/main/java/hudson/maven/MavenBuild.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@
5050
import hudson.util.DescribableList;
5151
import hudson.util.IOUtils;
5252
import org.apache.maven.BuildFailureException;
53-
import org.apache.maven.artifact.versioning.ComparableVersion;
5453
import org.apache.maven.execution.MavenSession;
5554
import org.apache.maven.execution.ReactorManager;
5655
import org.apache.maven.lifecycle.LifecycleExecutionException;
@@ -478,6 +477,7 @@ public void start() {
478477
onStartBuilding();
479478
startTime = System.currentTimeMillis();
480479
try {
480+
sync();
481481
listener.setSideOutputStream(log);
482482
} catch (IOException e) {
483483
e.printStackTrace();
@@ -491,6 +491,7 @@ public void end() {
491491
duration += System.currentTimeMillis()- startTime;
492492
parentBuild.notifyModuleBuild(MavenBuild.this);
493493
try {
494+
sync();
494495
listener.setSideOutputStream(null);
495496
save();
496497
} catch (IOException e) {
@@ -503,18 +504,33 @@ public void end() {
503504
*/
504505
public void appendLastLog() {
505506
try {
507+
sync();
506508
listener.setSideOutputStream(log);
507509
listener.setSideOutputStream(null);
508510
} catch (IOException e) {
509511
e.printStackTrace();
510512
}
511513
}
512514

515+
/**
516+
* Before we touch I/O streams, we need to make sure all the remote I/O operations are locally completed,
517+
* or else we end up switching the log traffic at unaligned moments.
518+
*/
519+
private void sync() {
520+
try {
521+
Channel.current().syncLocalIO();
522+
} catch (InterruptedException e) {
523+
// our signature doesn't allow us to throw InterruptedException, so we process it later
524+
Thread.currentThread().interrupt();
525+
}
526+
}
527+
513528
/**
514529
* Performs final clean up. Invoked after the entire aggregator build is completed.
515530
*/
516531
protected void close() {
517532
try {
533+
sync();
518534
log.close();
519535
} catch (IOException e) {
520536
e.printStackTrace();

maven-plugin/src/main/java/hudson/maven/SplittableBuildListener.java

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,9 @@ final class SplittableBuildListener extends AbstractTaskListener implements Buil
5555
* Used to accumulate data when no one is claiming the {@link #side},
5656
* so that the next one who set the {@link #side} can claim all the data.
5757
*/
58-
private ByteArrayOutputStream unclaimed = new ByteArrayOutputStream();
58+
private final ByteArrayOutputStream unclaimed = new ByteArrayOutputStream();
5959

60-
private OutputStream side = unclaimed;
60+
private volatile OutputStream side = unclaimed;
6161

6262
/**
6363
* Constant {@link PrintStream} connected to both {@link #core} and {@link #side}.
@@ -95,8 +95,10 @@ public void setSideOutputStream(OutputStream os) throws IOException {
9595
if(os==null) {
9696
os = unclaimed;
9797
} else {
98-
unclaimed.writeTo(os);
99-
unclaimed = new ByteArrayOutputStream();
98+
synchronized (unclaimed) {
99+
unclaimed.writeTo(os);
100+
unclaimed.reset();
101+
}
100102
}
101103
this.side = os;
102104
}

0 commit comments

Comments
 (0)