Hi Andrey, if NCDFEs are fine in your app you can always wrap and rethrow to signal that you think it's fine.
"An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions. The ThreadDeath error, though a "normal" condition, is also a subclass of Error because most applications should not try to catch it. A method is not required to declare in its throws clause any subclasses of Error that might be thrown during the execution of the method but not caught, since these errors are abnormal conditions that should never occur." - https://docs.oracle.com/javase/6/docs/api/java/lang/Error.html We should most definitely improve the documentation on this, as you note. On Wed, Feb 11, 2015 at 4:53 PM, Andrey <andrewkor...@hotmail.com> wrote: > Hi Viktor, > > Thank you for your reply! > > My issue at the moment is not so much lack of any type of guarantees while > processing a fatal exception (which indeed can be improved), but the fact > that - as the unit test demonstrates - Akka is unable to shut down itself > cleanly. > > Besides, "fatal" exceptions like NoClassDefFoundError do not make JVM > unstable or inconsistent like some others may (the VirtualMachineError > subclasses, for example), so in my mind there is no reason for Akka not to > try its best and shutdown cleanly under any conditions. > > Regards > Andrey > > On Wednesday, February 11, 2015 at 4:53:46 AM UTC-8, √ wrote: >> >> Hi Andrey, >> >> Thanks for your email, I've attempted to elucidate the current semantics >> but there may definitely be room for improvements. >> >> On 10 Feb 2015 17:23, "Andrey" <andrew...@hotmail.com> wrote: >> > >> > 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. >> >> it is only the catchall (NonFatal) that considers it fatal, if you expect >> it [NCDFE] in your code, you can/should surround it with a try catch and >> promote it to a non fatal exception or otherwise deal with the "normal" >> case. "Generic" NCDFEs are definitely not recoverable as they typically >> signal that the classpath/application is broken. >> >> > >> > 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. >> >> In the face of a fatal error no guarantees can be made as to the >> consistency of the JVM nor the data within it, as such we recommend to >> forcibly shut down the JVM. >> >> >Please note that the siblings of the failed actor (as well as all other >> unrelated actors) do get their postStop() invoked. >> >> Since `postStop` is invoked in the -instance- that produced a fatal >> failure I guess there's the philosophical argument to be had whether it can >> attempt to stop itself or not. >> >> > >> > 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. >> >> That is not a guarantee that can be made nor kept on the JVM as thread >> interruption is cooperative and thread stop is undefined. >> >> > >> > 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 akka-user+...@googlegroups.com. >> > To post to this group, send email to akka...@googlegroups.com. >> > Visit this group at http://groups.google.com/group/akka-user. >> > For more options, visit https://groups.google.com/d/optout. >> >> -- > >>>>>>>>>> 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 akka-user+unsubscr...@googlegroups.com. > To post to this group, send email to akka-user@googlegroups.com. > Visit this group at http://groups.google.com/group/akka-user. > For more options, visit https://groups.google.com/d/optout. > -- Cheers, √ -- >>>>>>>>>> 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 akka-user+unsubscr...@googlegroups.com. To post to this group, send email to akka-user@googlegroups.com. Visit this group at http://groups.google.com/group/akka-user. For more options, visit https://groups.google.com/d/optout.