From 04be9be9ab98776e2faf5cad7f2a3823a9f723b2 Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Mon, 15 Mar 2021 14:50:08 +0530 Subject: [PATCH] [junitlauncher] Don't let the PipedInputStream.read()s continue when the main thread exits Related to https://bz.apache.org/bugzilla/show_bug.cgi?id=64733 The main "writer" thread which initiates the writes to the PipedOutputStream (via the switched System.out/System.err) would exit/complete but would leave the SysOutErrStreamReader thread alive thus causing the PipedInputStream.read()s to continue happening in that SysOutErrStreamReader thread. This would cause the following IOException because the writer thread has exited and is no longer alive: [junitlauncher] Caused by: java.io.IOException: Pipe broken [junitlauncher] at java.base/java.io.PipedInputStream.read(PipedInputStream.java:321) [junitlauncher] at java.base/java.io.PipedInputStream.read(PipedInputStream.java:377) [junitlauncher] at java.base/java.io.InputStream.read(InputStream.java:205) [junitlauncher] at org.apache.tools.ant.taskdefs.optional.junitlauncher.LauncherSupport$SysOutErrStreamReader.run(LauncherSupport.java:525) [junitlauncher] ... 1 more --- .../junitlauncher/LauncherSupport.java | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/LauncherSupport.java b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/LauncherSupport.java index d83f86214..d96876d27 100644 --- a/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/LauncherSupport.java +++ b/src/main/org/apache/tools/ant/taskdefs/optional/junitlauncher/LauncherSupport.java @@ -44,6 +44,7 @@ import org.junit.platform.launcher.core.LauncherFactory; import org.junit.platform.launcher.listeners.SummaryGeneratingListener; import org.junit.platform.launcher.listeners.TestExecutionSummary; +import java.io.Closeable; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; @@ -153,6 +154,29 @@ public class LauncherSupport { } catch (Exception e) { // ignore } + // close the streams that we had used to redirect System.out/System.err + try { + firstListener.switchedSysOutHandle.ifPresent((h) -> { + try { + h.close(); + } catch (Exception e) { + // ignore + } + }); + } catch (Exception e) { + // ignore + } + try { + firstListener.switchedSysErrHandle.ifPresent((h) -> { + try { + h.close(); + } catch (Exception e) { + // ignore + } + }); + } catch (Exception e) { + // ignore + } } handleTestExecutionCompletion(test, firstListener.getSummary()); } finally { @@ -600,7 +624,7 @@ public class LauncherSupport { } } - private final class SwitchedStreamHandle { + private final class SwitchedStreamHandle implements AutoCloseable { private final PipedOutputStream outputStream; private final SysOutErrStreamReader streamReader; @@ -608,6 +632,12 @@ public class LauncherSupport { this.streamReader = streamReader; this.outputStream = outputStream; } + + @Override + public void close() throws Exception { + outputStream.close(); + streamReader.sourceStream.close(); + } } private final class Listener extends SummaryGeneratingListener {