Skip to content

Commit 36e941d

Browse files
authored
Merge pull request #205 from som-snytt/issue/10276
Do not merge throwable to itself
2 parents b68f3a2 + daa808c commit 36e941d

File tree

2 files changed

+50
-6
lines changed

2 files changed

+50
-6
lines changed

core/src/main/scala/scala/collection/parallel/Tasks.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,12 +68,12 @@ trait Task[R, +Tp] {
6868
mergeThrowables(that)
6969
}
7070

71-
private[parallel] def mergeThrowables(that: Task[_, _]): Unit = {
72-
if (this.throwable != null && that.throwable != null)
73-
this.throwable.addSuppressed(that.throwable)
74-
else if (this.throwable == null && that.throwable != null)
71+
private[parallel] def mergeThrowables(that: Task[_, _]): Unit =
72+
if (this.throwable != null) {
73+
if (that.throwable != null && (this.throwable ne that.throwable))
74+
this.throwable.addSuppressed(that.throwable)
75+
} else if (that.throwable != null)
7576
this.throwable = that.throwable
76-
}
7777

7878
// override in concrete task implementations to signal abort to other tasks
7979
private[parallel] def signalAbort(): Unit = {}

junit/src/test/scala/scala/collection/parallel/TaskTest.scala

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,12 @@ class TaskTest {
2929
t
3030
}
3131
}
32-
def mkPool(name: String) = new ForkJoinPool(1, mkFactory(name), null, false)
32+
def mkPool(name: String) = {
33+
val parallelism = 1
34+
val handler: Thread.UncaughtExceptionHandler = null
35+
val asyncMode = false
36+
new ForkJoinPool(parallelism, mkFactory(name), handler, asyncMode)
37+
}
3338

3439
val one = List(1).par
3540
val two = List(2).par
@@ -48,4 +53,43 @@ class TaskTest {
4853
val r = c.filter(_ != 0).map(_ + 1)
4954
assertSame(myTs, r.tasksupport)
5055
}
56+
57+
// was: Wrong exception: expected scala.collection.parallel.TaskTest$SpecialControl$1 but was java.lang.IllegalArgumentException
58+
@Test
59+
def `t10276 exception does not suppress itself when merging`: Unit = {
60+
import TestSupport._
61+
import scala.util.control.ControlThrowable
62+
class SpecialControl extends ControlThrowable("special")
63+
val SpecialExcept = new SpecialControl
64+
65+
class Special {
66+
def add(other: Special): Special = throw SpecialExcept
67+
}
68+
69+
def listed(n: Int) = List.fill(n)(new Special)
70+
val specials = listed(1000).par
71+
assertThrows[SpecialControl](_ eq SpecialExcept)(specials.reduce(_ add _))
72+
}
73+
}
74+
object TestSupport {
75+
import scala.reflect.ClassTag
76+
import scala.util.control.{ControlThrowable, NonFatal}
77+
private val Unthrown = new ControlThrowable {}
78+
79+
def assertThrows[T <: Throwable: ClassTag](checker: T => Boolean)(body: => Any): Unit =
80+
try {
81+
body
82+
throw Unthrown
83+
} catch {
84+
case Unthrown => fail("Expression did not throw!")
85+
case e: T if checker(e) => ()
86+
case failed: T =>
87+
val ae = new AssertionError(s"Exception failed check: $failed")
88+
ae.addSuppressed(failed)
89+
throw ae
90+
case NonFatal(other) =>
91+
val ae = new AssertionError(s"Wrong exception: expected ${implicitly[ClassTag[T]]} but was ${other.getClass.getName}")
92+
ae.addSuppressed(other)
93+
throw ae
94+
}
5195
}

0 commit comments

Comments
 (0)