Fix intercept of Watch in use of safe remote features #27333 (#27334)

And added one more case for cluster watcher, watching remote no cluster watchee, and the reverse.
This commit is contained in:
Helena Edelson 2019-07-12 12:18:37 -07:00 committed by GitHub
parent d27be3fa48
commit a110be8f69
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 298 additions and 19 deletions

View file

@ -688,21 +688,30 @@ private[akka] class RemoteActorRef private[akka] (
def isWatchIntercepted(watchee: ActorRef, watcher: ActorRef): Boolean = {
// If watchee != this then watcher should == this. This is a reverse watch, and it is not intercepted
// If watchee == this, only the watches from remoteWatcher are sent on the wire, on behalf of other watchers
val intercept = provider.remoteWatcher.exists(remoteWatcher => watcher != remoteWatcher) && watchee == this
if (intercept) provider.warnIfUnsafeDeathwatchWithoutCluster(watchee, watcher, "remote Watch/Unwatch")
intercept
provider.remoteWatcher.exists(remoteWatcher => watcher != remoteWatcher) && watchee == this
}
def sendSystemMessage(message: SystemMessage): Unit =
try {
//send to remote, unless watch message is intercepted by the remoteWatcher
message match {
case Watch(watchee, watcher) if isWatchIntercepted(watchee, watcher) =>
provider.remoteWatcher.foreach(_ ! RemoteWatcher.WatchRemote(watchee, watcher))
case Watch(watchee, watcher) =>
if (isWatchIntercepted(watchee, watcher))
provider.remoteWatcher.foreach(_ ! RemoteWatcher.WatchRemote(watchee, watcher))
else if (provider.remoteWatcher.isDefined)
remote.send(message, OptionVal.None, this)
else
provider.warnIfUnsafeDeathwatchWithoutCluster(watchee, watcher, "remote Watch")
//Unwatch has a different signature, need to pattern match arguments against InternalActorRef
case Unwatch(watchee: InternalActorRef, watcher: InternalActorRef) if isWatchIntercepted(watchee, watcher) =>
provider.remoteWatcher.foreach(_ ! RemoteWatcher.UnwatchRemote(watchee, watcher))
case _ => remote.send(message, OptionVal.None, this)
case Unwatch(watchee: InternalActorRef, watcher: InternalActorRef) =>
if (isWatchIntercepted(watchee, watcher))
provider.remoteWatcher.foreach(_ ! RemoteWatcher.UnwatchRemote(watchee, watcher))
else if (provider.remoteWatcher.isDefined)
remote.send(message, OptionVal.None, this)
case _ =>
remote.send(message, OptionVal.None, this)
}
} catch handleException(message, Actor.noSender)