Last active
January 6, 2021 17:01
-
-
Save aarondav/ca1f0cdcd50727f89c0d to your computer and use it in GitHub Desktop.
UncaughtExceptionHandler in ActorSystemImpl does not behave as hoped
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Must be in akka.actor package as ActorSystemImpl is protected[akka]. | |
package akka.actor | |
import java.util.concurrent.TimeUnit | |
import scala.concurrent.Future | |
import scala.concurrent.duration.FiniteDuration | |
import com.typesafe.config.ConfigFactory | |
/** Intended to provide a custom uncaught exception handler. DOES NOT WORK AS EXPECTED. */ | |
private[akka] class ExceptionCatchingActorSystemImpl(_name: String) | |
extends ActorSystemImpl(_name, ConfigFactory.empty(), ActorSystem.findClassLoader()) { | |
println("Custom actor system starting...") | |
protected override def uncaughtExceptionHandler = | |
new Thread.UncaughtExceptionHandler() { | |
def uncaughtException(thread: Thread, cause: Throwable): Unit = { | |
println("Exception observed:") // not called | |
cause.printStackTrace() | |
} | |
} | |
} | |
private object ExceptionCatchingActorSystemTest extends App { | |
val actorSystem = new ExceptionCatchingActorSystemImpl("MyActorSystem").start() | |
val actor = actorSystem.actorOf(Props(new TestActor())) | |
actor ! "Yo" | |
class TestActor extends Actor { | |
override def preStart() { | |
println("Started") | |
} | |
override def preRestart(reason: Throwable, message: Option[Any]) { | |
super.preRestart(reason, message) | |
println("preRestart called") // not called | |
} | |
def receive = { | |
case "Yo" => { | |
import context.dispatcher | |
Future { | |
throw new Error("Future error") | |
} | |
context.system.scheduler.scheduleOnce(new FiniteDuration(1, TimeUnit.MILLISECONDS)) { | |
throw new Error("Schedule error") | |
} | |
Thread.sleep(100) | |
throw new Error("Akka error") | |
} | |
} | |
} | |
} | |
/* Output: | |
[info] Running akka.actor.ExceptionCatchingActorSystemTest | |
[info] Custom actor system starting... | |
[info] Started | |
[info] [ERROR] [05/09/2014 12:31:35.415] [MyActorSystem-akka.actor.default-dispatcher-2] [TaskInvocation] Schedule error | |
[info] java.lang.Error: Schedule error | |
[info] at akka.actor.ExceptionCatchingActorSystemTest$TestActor$$anonfun$receive$1$$anonfun$applyOrElse$2.apply(IndestructibleActorSystem.scala:67) | |
[info] at akka.actor.ExceptionCatchingActorSystemTest$TestActor$$anonfun$receive$1$$anonfun$applyOrElse$2.apply(IndestructibleActorSystem.scala:67) | |
[info] at scala.Function0$class.apply$mcV$sp(Function0.scala:40) | |
[info] at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12) | |
[info] at akka.actor.Scheduler$$anon$11.run(Scheduler.scala:118) | |
[info] at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:42) | |
[info] at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:386) | |
[info] at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) | |
[info] at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) | |
[info] at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) | |
[info] at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107) | |
[info] | |
[info] [ERROR] [05/09/2014 12:31:35.507] [MyActorSystem-akka.actor.default-dispatcher-3] [LocalActorRefProvider(akka://MyActorSystem)] guardian failed, shutting down system | |
[info] java.lang.Error: Akka error | |
[info] at akka.actor.ExceptionCatchingActorSystemTest$TestActor$$anonfun$receive$1.applyOrElse(IndestructibleActorSystem.scala:71) | |
[info] at akka.actor.ActorCell.receiveMessage(ActorCell.scala:498) | |
[info] at akka.actor.ActorCell.invoke(ActorCell.scala:456) | |
[info] at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:237) | |
[info] at akka.dispatch.Mailbox.run(Mailbox.scala:219) | |
[info] at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:386) | |
[info] at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) | |
[info] at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) | |
[info] at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) | |
[info] at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107) | |
[info] | |
[info] [ERROR] [05/09/2014 12:31:35.507] [MyActorSystem-akka.actor.default-dispatcher-3] [akka://MyActorSystem/user] Akka error | |
[info] java.lang.Error: Akka error | |
[info] at akka.actor.ExceptionCatchingActorSystemTest$TestActor$$anonfun$receive$1.applyOrElse(IndestructibleActorSystem.scala:71) | |
[info] at akka.actor.ActorCell.receiveMessage(ActorCell.scala:498) | |
[info] at akka.actor.ActorCell.invoke(ActorCell.scala:456) | |
[info] at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:237) | |
[info] at akka.dispatch.Mailbox.run(Mailbox.scala:219) | |
[info] at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:386) | |
[info] at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) | |
[info] at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) | |
[info] at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) | |
[info] at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107) | |
[info] | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I think you did it right, it is just that uncaught exceptions in an Actor's receive doesn't get handled by the uncaught exception handler of the thread, because it is getting handled by the Actor framework before reaching it: https://doc.akka.io/docs/akka/current/fault-tolerance.html
We wanted to change the default uncaught handler of Akka and your gist helped me, thanks: https://stackoverflow.com/questions/65566743/how-do-i-get-the-stacktrace-of-uncaught-exceptions-in-an-akka-actor-system