From c01db5fbdd982a9613d1d64e2ac54f1b5c73b63c Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Fri, 20 Sep 2013 22:41:53 +0100
Subject: Lock around read/write of ScenePresence.m_originRegionID to make sure
that all threads are seeing the latest value and not a cached one.
There is a possibilty that some V2 teleport failures are due to the viewer triggered CompleteMovement thread not seeing the change of m_originRegionID by the UpdateAgent thread.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 38 ++++++++++++++++++++----
1 file changed, 33 insertions(+), 5 deletions(-)
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index f12d629..8d72e18 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -311,7 +311,21 @@ namespace OpenSim.Region.Framework.Scenes
///
private string m_callbackURI;
- public UUID m_originRegionID;
+ ///
+ /// Records the region from which this presence originated, if not from login.
+ ///
+ ///
+ /// Also acts as a signal in the teleport V2 process to release UpdateAgent after a viewer has triggered
+ /// CompleteMovement and made the previous child agent a root agent.
+ ///
+ private UUID m_originRegionID;
+
+ ///
+ /// This object is used as a lock before accessing m_originRegionID to make sure that every thread is seeing
+ /// the very latest value and not using some cached version. Cannot make m_originRegionID itself volatite as
+ /// it is a value type.
+ ///
+ private object m_originRegionIDAccessLock = new object();
///
/// Used by the entity transfer module to signal when the presence should not be closed because a subsequent
@@ -1359,13 +1373,21 @@ namespace OpenSim.Region.Framework.Scenes
// m_originRegionID is UUID.Zero; after, it's non-Zero. The CompleteMovement sequence initiated from the
// viewer (in turn triggered by the source region sending it a TeleportFinish event) waits until it's non-zero
int count = 50;
- while (m_originRegionID.Equals(UUID.Zero) && count-- > 0)
+ UUID originID;
+
+ lock (m_originRegionIDAccessLock)
+ originID = m_originRegionID;
+
+ while (originID.Equals(UUID.Zero) && count-- > 0)
{
+ lock (m_originRegionIDAccessLock)
+ originID = m_originRegionID;
+
m_log.DebugFormat("[SCENE PRESENCE]: Agent {0} waiting for update in {1}", client.Name, Scene.Name);
Thread.Sleep(200);
}
- if (m_originRegionID.Equals(UUID.Zero))
+ if (originID.Equals(UUID.Zero))
{
// Movement into region will fail
m_log.WarnFormat("[SCENE PRESENCE]: Update agent {0} never arrived in {1}", client.Name, Scene.Name);
@@ -1444,7 +1466,12 @@ namespace OpenSim.Region.Framework.Scenes
"[SCENE PRESENCE]: Releasing {0} {1} with callback to {2}",
client.Name, client.AgentId, m_callbackURI);
- Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI);
+ UUID originID;
+
+ lock (m_originRegionIDAccessLock)
+ originID = m_originRegionID;
+
+ Scene.SimulationService.ReleaseAgent(originID, UUID, m_callbackURI);
m_callbackURI = null;
}
// else
@@ -3461,7 +3488,8 @@ namespace OpenSim.Region.Framework.Scenes
private void CopyFrom(AgentData cAgent)
{
- m_originRegionID = cAgent.RegionID;
+ lock (m_originRegionIDAccessLock)
+ m_originRegionID = cAgent.RegionID;
m_callbackURI = cAgent.CallbackURI;
// m_log.DebugFormat(
--
cgit v1.1