FUTURES: wrap exceptions re-thrown by Future
Exceptions re-thrown by resultOrException() do not contain the call stack where the throw is happening, which can be rather confusing for debugging (and it is actually losing valuable debug information). I propose to create a AkkaRethrownException or similar for wrapping them.
Leave a comment
on 2011-08-13 11:59 *
By viktorklang
But that is a rather breaking change...
on 2011-08-13 12:01 *
By viktorklang
Means that all exception handlers that expect the wrapped exception is not going to get the wrapper.
on 2011-08-14 17:26 *
By viktorklang
Why not just add a logging statement with debug visibility just prior to the rethrow and log the line number?
on 2011-08-14 20:16 *
By Derek Williams
I was pretty sure that the stack trace was recorded when the exception is actually created, not when it is thrown. Is there something specific that must be done get this behavior to appear? I tried it out in the REPL:
All the same stack trace no matter how it gets thrown, and it always originates within the dispatcher thread.
scala> import akka.dispatch.Future
import akka.dispatch.Future
scala> case class Boom(msg: String) { def goBoom = sys.error(msg) }
defined class Boom
scala> Boom("Make boom!")
res0: Boom = Boom(Make boom!)
scala> Future { res0.goBoom }
res1: akka.dispatch.Future[Nothing] = akka.dispatch.DefaultPromise@25310bde
scala> res1.get
java.lang.RuntimeException: Make boom!
at scala.sys.package$.error(package.scala:27)
at Boom.goBoom(<console>:8)
at $anonfun$1.apply(<console>:12)
at $anonfun$1.apply(<console>:12)
at akka.dispatch.Future$$anonfun$apply$1.liftedTree1$1(Future.scala:241)
at akka.dispatch.Future$$anonfun$apply$1.apply$mcV$sp(Future.scala:240)
at akka.dispatch.TaskInvocation.run(MessageHandling.scala:32)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
at akka.dispatch.MonitorableThread.run(ThreadPoolBuilder.scala:187)
scala> res1.resultOrException
java.lang.RuntimeException: Make boom!
at scala.sys.package$.error(package.scala:27)
at Boom.goBoom(<console>:8)
at $anonfun$1.apply(<console>:12)
at $anonfun$1.apply(<console>:12)
at akka.dispatch.Future$$anonfun$apply$1.liftedTree1$1(Future.scala:241)
at akka.dispatch.Future$$anonfun$apply$1.apply$mcV$sp(Future.scala:240)
at akka.dispatch.TaskInvocation.run(MessageHandling.scala:32)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
at akka.dispatch.MonitorableThread.run(ThreadPoolBuilder.scala:187)
scala> throw res1.exception.get
java.lang.RuntimeException: Make boom!
at scala.sys.package$.error(package.scala:27)
at Boom.goBoom(<console>:8)
at $anonfun$1.apply(<console>:12)
at $anonfun$1.apply(<console>:12)
at akka.dispatch.Future$$anonfun$apply$1.liftedTree1$1(Future.scala:241)
at akka.dispatch.Future$$anonfun$apply$1.apply$mcV$sp(Future.scala:240)
at akka.dispatch.TaskInvocation.run(MessageHandling.scala:32)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
at akka.dispatch.MonitorableThread.run(ThreadPoolBuilder.scala:187)
All the same stack trace no matter how it gets thrown, and it always originates within the dispatcher thread.
on 2011-08-14 20:17 *
By Derek Williams
Oh wait.... I think I misunderstood. You want the stacktrace to show it is coming from resultOrException, right? Doh!
on 2011-10-07 10:41 *
By viktorklang
Summary changed from wrap exceptions re-thrown by Future to FUTURES: wrap exceptions re-thrown by Future
I think this needs to be closed an invalid. I don't want to use a wrapper since it destroys catch-clauses.
I've experimented using Object.clone but most Throwables aren't clonable, otherwise I could've just done clone().asInstanceOf[Throwable].setStackTrace(Thread.currentThread.getStackTrace)
I've experimented using Object.clone but most Throwables aren't clonable, otherwise I could've just done clone().asInstanceOf[Throwable].setStackTrace(Thread.currentThread.getStackTrace)