diff --git a/akka-actor/src/main/scala/akka/actor/ActorCell.scala b/akka-actor/src/main/scala/akka/actor/ActorCell.scala index 90500cfc88..a07e60ea45 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorCell.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorCell.scala @@ -5,16 +5,15 @@ package akka.actor import java.io.{ ObjectOutputStream, NotSerializableException } - import scala.annotation.tailrec import scala.collection.immutable.TreeSet import scala.concurrent.util.Duration import scala.util.control.NonFatal - import akka.actor.cell.ChildrenContainer import akka.dispatch.{ Watch, Unwatch, Terminate, SystemMessage, Suspend, Supervise, Resume, Recreate, NoMessage, MessageDispatcher, Envelope, Create, ChildTerminated } import akka.event.Logging.{ LogEvent, Debug, Error } import akka.japi.Procedure +import akka.dispatch.NullMessage /** * The actor context - the view of the actor cell from the actor. @@ -365,6 +364,7 @@ private[akka] class ActorCell( publish(Debug(self.path.toString, clazz(actor), "received AutoReceiveMessage " + msg)) msg.message match { + case NullMessage ⇒ // do nothing case Failed(cause, uid) ⇒ handleFailure(sender, cause, uid) case t @ Terminated(actor) ⇒ getChildByRef(actor) match { diff --git a/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala b/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala index 5c64e5554b..e71782869d 100644 --- a/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala +++ b/akka-actor/src/main/scala/akka/actor/ActorRefProvider.scala @@ -360,6 +360,7 @@ class LocalActorRefProvider( override def !(message: Any)(implicit sender: ActorRef = null): Unit = stopped.ifOff(message match { case Failed(ex, _) if sender ne null ⇒ causeOfTermination = Some(ex); sender.asInstanceOf[InternalActorRef].stop() + case NullMessage ⇒ // do nothing case _ ⇒ log.error(this + " received unexpected message [" + message + "]") }) diff --git a/akka-actor/src/main/scala/akka/actor/cell/Dispatch.scala b/akka-actor/src/main/scala/akka/actor/cell/Dispatch.scala index 794c051eed..5702ee91cb 100644 --- a/akka-actor/src/main/scala/akka/actor/cell/Dispatch.scala +++ b/akka-actor/src/main/scala/akka/actor/cell/Dispatch.scala @@ -10,6 +10,7 @@ import akka.dispatch.{ Terminate, SystemMessage, Suspend, Resume, Recreate, Mess import akka.event.Logging.Error import akka.util.Unsafe import scala.util.control.NonFatal +import akka.dispatch.NullMessage private[akka] trait Dispatch { this: ActorCell ⇒ @@ -56,6 +57,7 @@ private[akka] trait Dispatch { this: ActorCell ⇒ if (sendSupervise) { // ➡➡➡ NEVER SEND THE SAME SYSTEM MESSAGE OBJECT TO TWO ACTORS ⬅⬅⬅ parent.sendSystemMessage(akka.dispatch.Supervise(self, uid)) + parent.tell(NullMessage) } // This call is expected to start off the actor by scheduling its mailbox. diff --git a/akka-actor/src/main/scala/akka/dispatch/AbstractDispatcher.scala b/akka-actor/src/main/scala/akka/dispatch/AbstractDispatcher.scala index 3792748b02..45aac0279f 100644 --- a/akka-actor/src/main/scala/akka/dispatch/AbstractDispatcher.scala +++ b/akka-actor/src/main/scala/akka/dispatch/AbstractDispatcher.scala @@ -37,6 +37,13 @@ object Envelope { } } +/** + * This message is sent directly after the Supervise system message in order + * to form a barrier wrt. the first real message sent by the child, so that e.g. + * Failed() cannot overtake Supervise(). Processing this does nothing. + */ +case object NullMessage extends AutoReceivedMessage + /** * INTERNAL API */