redo ChildTerminated() processing, see #2391"

the previous patch of including the UID in the Terminated message did
suffer from the system vs. normal message ordering problem, hence I
reverted the previous fix and replaced it by sending a NullMessage after
ChildTerminated, exactly like in the Supervise case.
This commit is contained in:
Roland 2012-08-22 16:44:35 +02:00
parent d110836629
commit 43170ff168
10 changed files with 17 additions and 23 deletions

View file

@ -214,7 +214,7 @@ class ActorSystemSpec extends AkkaSpec("""akka.extensions = ["akka.actor.TestExt
EventFilter[Exception]("hello", occurrences = 1) intercept {
a ! "die"
}
val t = probe.expectMsg(Terminated(a)(true, 0))
val t = probe.expectMsg(Terminated(a)(true))
t.existenceConfirmed must be(true)
}

View file

@ -63,10 +63,7 @@ case object Kill extends Kill {
* When Death Watch is used, the watcher will receive a Terminated(watched) message when watched is terminated.
*/
@SerialVersionUID(1L)
case class Terminated private[akka] (@BeanProperty actor: ActorRef)(
@BeanProperty val existenceConfirmed: Boolean,
private[akka] val uid: Int)
extends AutoReceivedMessage
case class Terminated private[akka] (@BeanProperty actor: ActorRef)(@BeanProperty val existenceConfirmed: Boolean) extends AutoReceivedMessage
abstract class ReceiveTimeout extends PossiblyHarmful

View file

@ -376,13 +376,7 @@ private[akka] class ActorCell(
msg.message match {
case Failed(cause, uid) handleFailure(sender, cause, uid)
case t @ Terminated(actor)
getChildByRef(actor) match {
case Some(crs) if crs.uid == t.uid removeChild(actor)
case _
}
watchedActorTerminated(t.actor)
receiveMessage(t)
case t: Terminated watchedActorTerminated(t.actor); receiveMessage(t)
case Kill throw new ActorKilledException("Kill")
case PoisonPill self.stop()
case SelectParent(m) parent.tell(m, msg.sender)

View file

@ -441,7 +441,7 @@ private[akka] class EmptyLocalActorRef(override val provider: ActorRefProvider,
protected def specialHandle(msg: Any): Boolean = msg match {
case w: Watch
if (w.watchee == this && w.watcher != this)
w.watcher ! Terminated(w.watchee)(existenceConfirmed = false, 0)
w.watcher ! Terminated(w.watchee)(existenceConfirmed = false)
true
case _: Unwatch true // Just ignore
case _ false
@ -466,9 +466,10 @@ private[akka] class DeadLetterActorRef(_provider: ActorRefProvider,
override protected def specialHandle(msg: Any): Boolean = msg match {
case w: Watch
if (w.watchee != this && w.watcher != this)
w.watcher ! Terminated(w.watchee)(existenceConfirmed = false, 0)
w.watcher ! Terminated(w.watchee)(existenceConfirmed = false)
true
case w: Unwatch true // Just ignore
case NullMessage true
case _ false
}

View file

@ -94,7 +94,7 @@ private[akka] trait Children { this: ActorCell ⇒
swapChildrenRefs(c, c.shallDie(ref)) || shallDie(ref)
}
@tailrec final protected def removeChild(ref: ActorRef): ChildrenContainer = {
@tailrec final private def removeChild(ref: ActorRef): ChildrenContainer = {
val c = childrenRefs
val n = c.remove(ref)
if (swapChildrenRefs(c, n)) n

View file

@ -36,7 +36,7 @@ private[akka] trait DeathWatch { this: ActorCell ⇒
protected def tellWatchersWeDied(actor: Actor): Unit = {
if (!watchedBy.isEmpty) {
val terminated = Terminated(self)(existenceConfirmed = true, uid)
val terminated = Terminated(self)(existenceConfirmed = true)
try {
watchedBy foreach {
watcher

View file

@ -11,6 +11,7 @@ import akka.event.Logging.{ Warning, Error, Debug }
import scala.util.control.NonFatal
import akka.dispatch.SystemMessage
import akka.event.Logging
import akka.dispatch.NullMessage
private[akka] trait FaultHandling { this: ActorCell
@ -157,6 +158,7 @@ private[akka] trait FaultHandling { this: ActorCell ⇒
try if (a ne null) a.postStop()
finally try dispatcher.detach(this)
finally try parent.sendSystemMessage(ChildTerminated(self))
finally try parent.tell(NullMessage) // read ScalaDoc of NullMessage to see why
finally try tellWatchersWeDied(a)
finally try unwatchWatchedActors(a)
finally {

View file

@ -262,7 +262,7 @@ private[akka] final class PromiseActorRef private (val provider: ActorRefProvide
case _: Terminate stop()
case Watch(watchee, watcher)
if (watchee == this && watcher != this) {
if (!addWatcher(watcher)) watcher ! Terminated(watchee)(existenceConfirmed = true, 0)
if (!addWatcher(watcher)) watcher ! Terminated(watchee)(existenceConfirmed = true)
} else System.err.println("BUG: illegal Watch(%s,%s) for %s".format(watchee, watcher, this))
case Unwatch(watchee, watcher)
if (watchee == this && watcher != this) remWatcher(watcher)
@ -281,7 +281,7 @@ private[akka] final class PromiseActorRef private (val provider: ActorRefProvide
result tryComplete Failure(new ActorKilledException("Stopped"))
val watchers = clearWatchers()
if (!watchers.isEmpty) {
val termination = Terminated(this)(existenceConfirmed = true, 0)
val termination = Terminated(this)(existenceConfirmed = true)
watchers foreach { w try w.tell(termination, this) catch { case NonFatal(t) /* FIXME LOG THIS */ } }
}
}