Skip to content

Commit 73f9a6c

Browse files
committed
Fix deadlock in runAll
1 parent 57a1177 commit 73f9a6c

File tree

3 files changed

+51
-49
lines changed

3 files changed

+51
-49
lines changed

compiler/test/dotty/tools/dotc/ParallelSummaryReport.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
public class ParallelSummaryReport {
1414
public final static boolean isInteractive = !System.getenv().containsKey("DRONE");
1515

16-
private static TestReporter rep = TestReporter.reporter(-1);
16+
private static TestReporter rep = TestReporter.reporter(System.out, -1);
1717
private static ArrayDeque<String> failedTests = new ArrayDeque<>();
1818
private static ArrayDeque<String> reproduceInstructions = new ArrayDeque<>();
1919
private static int passed;
@@ -36,7 +36,7 @@ public final static void addReproduceInstruction(String msg) {
3636
}
3737

3838
@BeforeClass public final static void setup() {
39-
rep = TestReporter.reporter(-1);
39+
rep = TestReporter.reporter(System.out, -1);
4040
failedTests = new ArrayDeque<>();
4141
reproduceInstructions = new ArrayDeque<>();
4242
}

compiler/test/dotty/tools/dotc/ParallelTesting.scala

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,8 @@ trait ParallelTesting { self =>
174174
* according to the implementing class "neg", "run" or "pos".
175175
*/
176176
private abstract class Test(testSources: List[TestSource], times: Int, threadLimit: Option[Int], suppressAllOutput: Boolean) {
177+
protected final val realStdout = System.out
178+
protected final val realStderr = System.err
177179

178180
/** Actual compilation run logic, the test behaviour is defined here */
179181
protected def compilationRunnable(testSource: TestSource): Runnable
@@ -192,10 +194,10 @@ trait ParallelTesting { self =>
192194
val sourceCount = filteredSources.length
193195

194196
private[this] var _errorCount = 0
195-
def errorCount: Int = synchronized { _errorCount }
197+
def errorCount: Int = _errorCount
196198

197199
private[this] var _testSourcesCompiled = 0
198-
private def testSourcesCompiled : Int = synchronized { _testSourcesCompiled }
200+
private def testSourcesCompiled: Int = _testSourcesCompiled
199201

200202
/** Complete the current compilation with the amount of errors encountered */
201203
protected final def registerCompilation(errors: Int) = synchronized {
@@ -228,7 +230,7 @@ trait ParallelTesting { self =>
228230

229231
/** Prints to `System.err` if we're not suppressing all output */
230232
protected def echo(msg: String): Unit =
231-
if (!suppressAllOutput) System.err.println(msg)
233+
if (!suppressAllOutput) realStderr.println(msg)
232234

233235
/** A single `Runnable` that prints a progress bar for the curent `Test` */
234236
private def createProgressMonitor: Runnable = new Runnable {
@@ -238,17 +240,19 @@ trait ParallelTesting { self =>
238240
while (tCompiled < sourceCount) {
239241
val timestamp = (System.currentTimeMillis - start) / 1000
240242
val progress = (tCompiled.toDouble / sourceCount * 40).toInt
241-
print(
243+
244+
realStdout.print(
242245
"[" + ("=" * (math.max(progress - 1, 0))) +
243246
(if (progress > 0) ">" else "") +
244247
(" " * (39 - progress)) +
245248
s"] compiling ($tCompiled/$sourceCount, ${timestamp}s)\r"
246249
)
250+
247251
Thread.sleep(100)
248252
tCompiled = testSourcesCompiled
249253
}
250254
// println, otherwise no newline and cursor at start of line
251-
println(
255+
realStdout.println(
252256
s"[=======================================] compiled ($sourceCount/$sourceCount, " +
253257
s"${(System.currentTimeMillis - start) / 1000}s) "
254258
)
@@ -259,7 +263,10 @@ trait ParallelTesting { self =>
259263
* if it did, the test should automatically fail.
260264
*/
261265
protected def tryCompile(testSource: TestSource)(op: => Unit): Unit =
262-
try op catch {
266+
try {
267+
if (!isInteractive) realStdout.println(s"Testing ${testSource.title}")
268+
op
269+
} catch {
263270
case NonFatal(e) => {
264271
// if an exception is thrown during compilation, the complete test
265272
// run should fail
@@ -309,8 +316,10 @@ trait ParallelTesting { self =>
309316
Runtime.getRuntime.exec(fullArgs).waitFor() == 0
310317
} else true
311318

312-
val reporter = TestReporter.parallelReporter(this, logLevel =
313-
if (suppressErrors || suppressAllOutput) ERROR + 1 else ERROR)
319+
val reporter =
320+
TestReporter.reporter(realStdout, logLevel =
321+
if (suppressErrors || suppressAllOutput) ERROR + 1 else ERROR)
322+
314323
val driver =
315324
if (times == 1) new Driver { def newCompiler(implicit ctx: Context) = new Compiler }
316325
else new Driver {
@@ -353,8 +362,12 @@ trait ParallelTesting { self =>
353362
}
354363

355364
pool.shutdown()
356-
if (!pool.awaitTermination(10, TimeUnit.MINUTES))
365+
if (!pool.awaitTermination(10, TimeUnit.MINUTES)) {
366+
pool.shutdownNow()
367+
System.setOut(realStdout)
368+
System.setErr(realStderr)
357369
throw new TimeoutException("Compiling targets timed out")
370+
}
358371

359372
if (didFail) {
360373
reportFailed()
@@ -417,16 +430,14 @@ trait ParallelTesting { self =>
417430
import java.net.{ URL, URLClassLoader }
418431

419432
val printStream = new ByteArrayOutputStream
420-
val oldOut = System.out
421-
val oldErr = System.err
422433

423434
try {
424435
// Do classloading magic and running here:
425436
val ucl = new URLClassLoader(Array(dir.toURI.toURL))
426437
val cls = ucl.loadClass("Test")
427438
val meth = cls.getMethod("main", classOf[Array[String]])
428439

429-
self.synchronized {
440+
synchronized {
430441
try {
431442
val ps = new PrintStream(printStream)
432443
System.setOut(ps)
@@ -436,9 +447,13 @@ trait ParallelTesting { self =>
436447
meth.invoke(null, Array("jvm")) // partest passes at least "jvm" as an arg
437448
}
438449
}
439-
} finally {
440-
System.setOut(oldOut)
441-
System.setErr(oldErr)
450+
System.setOut(realStdout)
451+
System.setErr(realStderr)
452+
} catch {
453+
case t: Throwable =>
454+
System.setOut(realStdout)
455+
System.setErr(realStderr)
456+
throw t
442457
}
443458
}
444459
}

compiler/test/dotty/tools/dotc/reporting/TestReporter.scala

Lines changed: 19 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package dotty.tools
22
package dotc
33
package reporting
44

5-
import java.io.{ PrintWriter, File => JFile, FileOutputStream }
5+
import java.io.{ PrintStream, PrintWriter, File => JFile, FileOutputStream }
66
import java.text.SimpleDateFormat
77
import java.util.Date
88

@@ -93,38 +93,25 @@ object TestReporter {
9393
logWriter.flush()
9494
}
9595

96-
def parallelReporter(lock: AnyRef, logLevel: Int): TestReporter = new TestReporter(
97-
new PrintWriter(Console.err, true),
98-
str => lock.synchronized {
99-
logWriter.println(str)
100-
logWriter.flush()
101-
},
102-
logLevel
103-
)
104-
105-
def reporter(logLevel: Int): TestReporter = new TestReporter(
106-
new PrintWriter(Console.err, true),
107-
writeToLog,
108-
logLevel
109-
)
110-
111-
def simplifiedReporter(writer: PrintWriter): TestReporter = new TestReporter(
112-
writer,
113-
writeToLog,
114-
WARNING
115-
) {
116-
/** Prints the message with the given position indication in a simplified manner */
117-
override def printMessageAndPos(m: MessageContainer, extra: String)(implicit ctx: Context): Unit = {
118-
val msg = s"${m.pos.line + 1}: " + m.contained.kind + extra
119-
val extraInfo = inlineInfo(m.pos)
120-
121-
writer.println(msg)
122-
_messageBuf.append(msg)
123-
124-
if (extraInfo.nonEmpty) {
125-
writer.println(extraInfo)
126-
_messageBuf.append(extraInfo)
96+
def reporter(ps: PrintStream, logLevel: Int): TestReporter =
97+
new TestReporter(new PrintWriter(ps, true), writeToLog, logLevel)
98+
99+
def simplifiedReporter(writer: PrintWriter): TestReporter = {
100+
val rep = new TestReporter(writer, writeToLog, WARNING) {
101+
/** Prints the message with the given position indication in a simplified manner */
102+
override def printMessageAndPos(m: MessageContainer, extra: String)(implicit ctx: Context): Unit = {
103+
val msg = s"${m.pos.line + 1}: " + m.contained.kind + extra
104+
val extraInfo = inlineInfo(m.pos)
105+
106+
writer.println(msg)
107+
_messageBuf.append(msg)
108+
109+
if (extraInfo.nonEmpty) {
110+
writer.println(extraInfo)
111+
_messageBuf.append(extraInfo)
112+
}
127113
}
128114
}
115+
rep
129116
}
130117
}

0 commit comments

Comments
 (0)