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:
parent
d110836629
commit
43170ff168
10 changed files with 17 additions and 23 deletions
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 ⇒
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 */ } }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue