diff --git a/akka-cluster/src/main/scala/akka/cluster/Cluster.scala b/akka-cluster/src/main/scala/akka/cluster/Cluster.scala index 18f57db99a..745bdb0066 100644 --- a/akka-cluster/src/main/scala/akka/cluster/Cluster.scala +++ b/akka-cluster/src/main/scala/akka/cluster/Cluster.scala @@ -339,7 +339,7 @@ class Cluster(val system: ExtendedActorSystem) extends Extension { /** * The supplied thunk will be run, once, when current cluster member is `Removed`. - * and if the cluster have been shutdown,that thunk will run on the caller thread immediately. + * If the cluster has already been shutdown the thunk will run on the caller thread immediately. * Typically used together `cluster.leave(cluster.selfAddress)` and then `system.shutdown()`. */ def registerOnMemberRemoved[T](code: ⇒ T): Unit = @@ -347,7 +347,7 @@ class Cluster(val system: ExtendedActorSystem) extends Extension { /** * Java API: The supplied thunk will be run, once, when current cluster member is `Removed`. - * and if the cluster have been shutdown,that thunk will run on the caller thread immediately. + * If the cluster has already been shutdown the thunk will run on the caller thread immediately. * Typically used together `cluster.leave(cluster.selfAddress)` and then `system.shutdown()`. */ def registerOnMemberRemoved(callback: Runnable): Unit = { diff --git a/akka-docs/rst/java/cluster-usage.rst b/akka-docs/rst/java/cluster-usage.rst index 4b1ce6279c..b21f914e4f 100644 --- a/akka-docs/rst/java/cluster-usage.rst +++ b/akka-docs/rst/java/cluster-usage.rst @@ -333,8 +333,7 @@ How To Cleanup when Member is Removed ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ You can do some clean up in a ``registerOnMemberRemoved`` callback, which will -be invoked when the current member status is changed to 'Removed' or the cluster have been shutdown,i.e. -terminate the actor system. +be invoked when the current member status is changed to 'Removed' or the cluster have been shutdown. For example, this is how to shut down the ``ActorSystem`` and thereafter exit the JVM: diff --git a/akka-docs/rst/scala/cluster-usage.rst b/akka-docs/rst/scala/cluster-usage.rst index b990b1b53c..58aa03d8c3 100644 --- a/akka-docs/rst/scala/cluster-usage.rst +++ b/akka-docs/rst/scala/cluster-usage.rst @@ -327,8 +327,7 @@ How To Cleanup when Member is Removed ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ You can do some clean up in a ``registerOnMemberRemoved`` callback, which will -be invoked when the current member status is changed to 'Removed' or the cluster have been shutdown,i.e. -terminate the actor system. +be invoked when the current member status is changed to 'Removed' or the cluster have been shutdown. For example, this is how to shut down the ``ActorSystem`` and thereafter exit the JVM: diff --git a/akka-samples/akka-sample-cluster-java/src/main/java/sample/cluster/factorial/FactorialFrontendMain.java b/akka-samples/akka-sample-cluster-java/src/main/java/sample/cluster/factorial/FactorialFrontendMain.java index ca9ccb1447..8a6317ef96 100644 --- a/akka-samples/akka-sample-cluster-java/src/main/java/sample/cluster/factorial/FactorialFrontendMain.java +++ b/akka-samples/akka-sample-cluster-java/src/main/java/sample/cluster/factorial/FactorialFrontendMain.java @@ -1,8 +1,10 @@ package sample.cluster.factorial; -import java.util.concurrent.TimeUnit; -import scala.concurrent.duration.FiniteDuration; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.TimeUnit; +import scala.concurrent.Await; +import scala.concurrent.duration.Duration; import com.typesafe.config.Config; import com.typesafe.config.ConfigFactory; @@ -38,18 +40,29 @@ public class FactorialFrontendMain { public void run() { // exit JVM when ActorSystem has been terminated final Runnable exit = new Runnable() { - @Override - public void run() { - System.exit(-1); + @Override public void run() { + System.exit(0); } }; system.registerOnTermination(exit); - // in case ActorSystem shutdown takes longer than 10 seconds, - // exit the JVM forcefully anyway - system.scheduler().scheduleOnce(FiniteDuration.create(10, TimeUnit.SECONDS), - exit, system.dispatcher()); + // shut down ActorSystem system.terminate(); + + // In case ActorSystem shutdown takes longer than 10 seconds, + // exit the JVM forcefully anyway. + // We must spawn a separate thread to not block current thread, + // since that would have blocked the shutdown of the ActorSystem. + new Thread() { + @Override public void run(){ + try { + Await.ready(system.whenTerminated(), Duration.create(10, TimeUnit.SECONDS)); + } catch (Exception e) { + System.exit(-1); + } + + } + }.start(); } }); //#registerOnRemoved diff --git a/akka-samples/akka-sample-cluster-scala/src/main/scala/sample/cluster/factorial/FactorialFrontend.scala b/akka-samples/akka-sample-cluster-scala/src/main/scala/sample/cluster/factorial/FactorialFrontend.scala index 64ef9bbdbc..16e49a9250 100644 --- a/akka-samples/akka-sample-cluster-scala/src/main/scala/sample/cluster/factorial/FactorialFrontend.scala +++ b/akka-samples/akka-sample-cluster-scala/src/main/scala/sample/cluster/factorial/FactorialFrontend.scala @@ -9,6 +9,8 @@ import akka.actor.Props import akka.cluster.Cluster import akka.routing.FromConfig import akka.actor.ReceiveTimeout +import scala.util.Try +import scala.concurrent.Await //#frontend class FactorialFrontend(upToN: Int, repeat: Boolean) extends Actor with ActorLogging { @@ -61,12 +63,20 @@ object FactorialFrontend { //#registerOnRemoved Cluster(system).registerOnMemberRemoved { // exit JVM when ActorSystem has been terminated - system.registerOnTermination(System.exit(-1)) - // in case ActorSystem shutdown takes longer than 10 seconds, - // exit the JVM forcefully anyway - system.scheduler.scheduleOnce(10.seconds)(System.exit(-1))(system.dispatcher) + system.registerOnTermination(System.exit(0)) // shut down ActorSystem system.terminate() + + // In case ActorSystem shutdown takes longer than 10 seconds, + // exit the JVM forcefully anyway. + // We must spawn a separate thread to not block current thread, + // since that would have blocked the shutdown of the ActorSystem. + new Thread { + override def run(): Unit = { + if (Try(Await.ready(system.whenTerminated, 10.seconds)).isFailure) + System.exit(-1) + } + }.start() } //#registerOnRemoved