Given the following code:
import scala.concurrent.ExecutionContext
import java.util.concurrent.Executors
val ec = ExecutionContext.fromExecutor(Executors.newFixedThreadPool(1))
val f = Future[Unit](throw new java.lang.InternalError())(ec)
The future f
never completes. f.value
is always None
.
There was a known bug in scala-2.10 that was fixed:
http://mandubian.com/2013/02/22/scala-future-fatal-exception
https://issues.scala-lang.org/browse/SI-7029
I am on scala-2.11.
The example from the bug report uses NotImplementedErorr, which is correctly handled by the Future and it will complete. However, if I use InternalError as in my example above, then the Future never completes. This is true whether I use the ExecutionContext.global, Executors.newSingleThreadExecutor, or Executors.newFixedThreadPool.
I can catch Throwable in the body of the Future and re-throw it with an exception wrapped around it that I know the Future will handle correctly, but that's a terrible solution.
Is this a known issue? Expected behavior? What options do I have to get sane behavior out of my Futures?
From the source of Future.
override def run() = {
promise complete {
try Success(body) catch { case NonFatal(e) => Failure(e) }
}
}
As you can see, Future
is only catching NonFatal
exception.
And the following is what NonFatal matches.
def apply(t: Throwable): Boolean = t match {
// VirtualMachineError includes OutOfMemoryError and other fatal errors
case _: VirtualMachineError | _: ThreadDeath | _: InterruptedException | _: LinkageError | _: ControlThrowable => false
case _ => true
}
Since java.lang.InternalError is subclass of VirtualMachineError
, the thread which is running the task is just killed by exception, and the promise will never be completed.
From the overview of the exceptions in the future
Fatal exceptions (as determined by NonFatal) are rethrown in the thread executing the failed asynchronous computation. This informs the code managing the executing threads of the problem and allows it to fail fast, if necessary. See NonFatal for a more precise description of the semantics.
Therefore I think this is intended behavior.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With