I have an actorsystem where i have registered some code on actorsystem termination. The code goes as follows -
object ChildActor {
class Msg
}
class ChildActor extends Actor {
val log = Logging(context.system, this)
override def receive: Receive = {
case a : String => log.info(s"received $a")
case _ : Msg => throw new OutOfMemoryError("error")
}
}
class ParentActor extends Actor {
override val supervisorStrategy = OneForOneStrategy() {
case _: OutOfMemoryError => {
Stop
}
case _: Exception => Stop
}
val child = context.actorOf(Props[ChildActor], "child")
override def receive: Receive = {
case a: String => child ! a
case msg : Msg => child ! msg
}
}
object Test extends App {
val customConf = ConfigFactory.parseString("""
akka {
jvm-exit-on-fatal-error = false
}
""")
val actorSystem = ActorSystem("OOMException", ConfigFactory.load(customConf))
actorSystem.registerOnTermination(println("going off"))
val actor = actorSystem.actorOf(Props[ParentActor], "parentActor")
actor ! new Msg
}
The wierd behaviour that i noticing is with my callbacks. When i run the app normally i never ever get the callback for my registered code.
However when i run in debug mode and i wait for few seconds inside the terminate() method then the line gets printed.. I am not sure why this few seconds of wait is making sure that all registered callbacks are fired whereas in the normal run mode it's not happening..Any idea anyone??
P.S : I know that OOM is fatal and but i am just curious about the problem in hand and OOM is just one scenario.
When i take a thread dump at the end i see that following two threads are always present -
"OOMException-akka.actor.default-dispatcher-2" #12 prio=5 os_prio=0 tid=0x000000001e8dd800 nid=0x1029c waiting on condition [0x0000000020eff000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x0000000770700c90> (a akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinPool)
at akka.dispatch.forkjoin.ForkJoinPool.scan(ForkJoinPool.java:2075)
at akka.dispatch.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
at akka.dispatch.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)
"OOMException-scheduler-1" #11 prio=5 os_prio=0 tid=0x000000001e5d8800 nid=0xfba4 waiting on condition [0x000000001f35e000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at akka.actor.LightArrayRevolverScheduler.waitNanos(LightArrayRevolverScheduler.scala:85)
at akka.actor.LightArrayRevolverScheduler$$anon$4.nextTick(LightArrayRevolverScheduler.scala:265)
at akka.actor.LightArrayRevolverScheduler$$anon$4.run(LightArrayRevolverScheduler.scala:235)
at java.lang.Thread.run(Thread.java:748)
The scheduler should have finished as the actor system terminated ..not sure why this is in a timed waiting state..
App
could be tricky here, maybe the JVM is terminated (because all threads left are daemon threads) before your callback can be executed.I would first suggest putting your app code in a
def main(...)
method.The use something like this instead of a
println
: