Hello,
I have Akka configured not to exit JVM on fatal errors by setting the
"akka.jvm-exit-on-fatal-error" property to "off". In such case, it's
expected to shutdown the actor system. (As a side note, I find Scala's
opinion as to which java.lang.Error are to be treated as fatal and
non-fatal to be mildly peculiar. One example would be the OSGi environment
where NoClassDefFoundError is not a fatal exception, but on the contrary,
is very much recoverable without a JVM restart. Scala disagrees.)
Anyway, back to the problem, Akka seems to recognize the setting correctly
and doesn't halt the JVM process. However, when later I call a shutdown()
followed by an awaitTermination() on the instance of the actor system whose
actor has just "fatally" failed, the awaitTermination() call never returns
(blocks forever). Also, neither the actor that has thrown the Error, nor
its parents (up the supervision tree) get called postStop(). It looks
almost like if Akka forgets to stop the failed actor and its immediate
parent is left waiting forever unable to proceed with its own shutdown.
Please note that the siblings of the failed actor (as well as all other
unrelated actors) do get their postStop() invoked.
Although I could not find anything relevant in Akka documentation, my
expectation is that postStop() of all actors is always invoked during actor
system shutdown.
Below is a simple unit test that demonstrates the problem.
Thanks you for your help.
Andrey
package example;
import java.util.concurrent.TimeUnit;
import akka.actor.ActorRef;
import akka.actor.ActorSystem;
import akka.actor.Props;
import akka.actor.UntypedActor;
import com.google.common.util.concurrent.SettableFuture;
import com.typesafe.config.ConfigFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import scala.concurrent.duration.Duration;
public class AkkaUtilTest {
ActorSystem akka;
@Before
public void setUp() throws Exception {
akka = ActorSystem.create("test",
ConfigFactory.parseString("akka.jvm-exit-on-fatal-error=off"
));
}
@After
public void tearDown() throws Exception {
akka.shutdown();
// This call never returns.
akka.awaitTermination(Duration.create(5000, TimeUnit.MILLISECONDS));
}
@Test(timeout = 2000)
public void testError() throws Exception {
SettableFuture<?> result = SettableFuture.create();
ActorRef actorRef = akka.actorOf(Props.create(ThrowingActor.class,
result));
actorRef.tell(new Object(), ActorRef.noSender());
// The get() call never returns and the test times out.
result.get();
}
static class ThrowingActor extends UntypedActor {
final SettableFuture<?> stopped;
ThrowingActor(SettableFuture<?> stopped) {
this.stopped = stopped;
}
@Override
public void onReceive(Object message) throws Exception {
// These cause postStop() never called on this actor and the
actor system can't be
// gracefully shutdown.
//throw new OutOfMemoryError("oh, my!");
throw new NoClassDefFoundError("no-class-def");
// These work just fine:
// throw new AssertionError("assertion");
// throw new Error("error");
}
@Override
public void postStop() throws Exception {
// Never called.
stopped.set(null);
}
}
}
--
>>>>>>>>>> Read the docs: http://akka.io/docs/
>>>>>>>>>> Check the FAQ:
>>>>>>>>>> http://doc.akka.io/docs/akka/current/additional/faq.html
>>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user
---
You received this message because you are subscribed to the Google Groups "Akka
User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.