From 206e2a3e5ef32f3bf65e0d85ca7f1309b6ae6eb8 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Tue, 14 Jul 2020 14:03:26 +1000 Subject: [PATCH] Avoid catching fatal errors as a Failed future scala-async 0.9.6 regressed and started catching fatal exceptions. For 1.0.0, we're fixing this regression and harmonizing the behaviour with direct use of the Future combinators. --- .../scala/scala/async/FutureStateMachine.scala | 16 ++++++++-------- src/test/scala/scala/async/ExceptionalTest.scala | 1 - 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/main/scala/scala/async/FutureStateMachine.scala b/src/main/scala/scala/async/FutureStateMachine.scala index 21fc21bf..7d016541 100644 --- a/src/main/scala/scala/async/FutureStateMachine.scala +++ b/src/main/scala/scala/async/FutureStateMachine.scala @@ -15,6 +15,7 @@ import java.util.Objects import scala.util.{Failure, Success, Try} import scala.concurrent.{ExecutionContext, Future, Promise} +import scala.util.control.NonFatal /** The base class for state machines generated by the `scala.async.Async.async` macro. * Not intended to be directly extended in user-written code. @@ -34,15 +35,14 @@ abstract class FutureStateMachine(execContext: ExecutionContext) extends Functio /** Assign `i` to the state variable */ protected def state_=(s: Int): Unit = state$async = s + NonFatal // eagerly classloading NonFatal to reduce the chance of a cascading StackOverflowError in `completeFailure` + /** Complete the state machine with the given failure. */ - protected def completeFailure(t: Throwable): Unit = { - // - // TODO https://github.com/scala/scala-async/issues/243 - // - // scala-async accidentally started catching NonFatal exceptions in: - // https://github.com/scala/scala-async/commit/e3ff0382ae4e015fc69da8335450718951714982#diff-136ab0b6ecaee5d240cd109e2b17ccb2R411 - // This follows the new behaviour but should we fix the regression? - result$async.complete(Failure(t)) + protected def completeFailure(t: Throwable): Unit = t match { + case NonFatal(t) => + result$async.complete(Failure(t)) + case _ => + throw t } /** Complete the state machine with the given value. */ diff --git a/src/test/scala/scala/async/ExceptionalTest.scala b/src/test/scala/scala/async/ExceptionalTest.scala index 0ae8c70a..67751027 100644 --- a/src/test/scala/scala/async/ExceptionalTest.scala +++ b/src/test/scala/scala/async/ExceptionalTest.scala @@ -18,7 +18,6 @@ class ExceptionalTest { } @Test - @Ignore // TODO https://github.com/scala/scala-async/issues/243 def nonFatalNotCaughtAsync(): Unit = { check { implicit ec => async {