aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/CoreModules/Framework
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2012-05-14 18:36:26 +0100
committerJustin Clark-Casey (justincc)2012-05-14 18:36:26 +0100
commitc2aa3b90d9d367bcaeba93352ef6b0f513e663f7 (patch)
treeda532e0b514f7f7b143db0a7f9cc0731ae02112f /OpenSim/Region/CoreModules/Framework
parentMerge branch 'master' of ssh://opensimulator.org/var/git/opensim (diff)
downloadopensim-SC-c2aa3b90d9d367bcaeba93352ef6b0f513e663f7.zip
opensim-SC-c2aa3b90d9d367bcaeba93352ef6b0f513e663f7.tar.gz
opensim-SC-c2aa3b90d9d367bcaeba93352ef6b0f513e663f7.tar.bz2
opensim-SC-c2aa3b90d9d367bcaeba93352ef6b0f513e663f7.tar.xz
Set the agent in transit teleport flag at the first available opportunity (i.e. when IsInTransit() was being checked) to close down a race condition.
On EntityTransferModule.DoTeleport() there was an IsInTransit() check to prevent multiple simultaneous teleport attempts. However, the SetInTransit() was only performed later on, which left a window in which multiple threads could pass the IsInTransit() check. This has been seen in the field and the results aren't pretty. This commit effectively combines the IsInTransit() and SetInTransit() checks so there is no such window. More failure cases are made to to call ResetInTransit() to adjust to this move.
Diffstat (limited to 'OpenSim/Region/CoreModules/Framework')
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs48
1 files changed, 37 insertions, 11 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 9766a25..d0aead5 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -210,6 +210,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
210 sp.Name, sp.AbsolutePosition, sp.Scene.RegionInfo.RegionName, position, destinationRegionName, 210 sp.Name, sp.AbsolutePosition, sp.Scene.RegionInfo.RegionName, position, destinationRegionName,
211 e.Message, e.StackTrace); 211 e.Message, e.StackTrace);
212 212
213 // Make sure that we clear the in-transit flag so that future teleport attempts don't always fail.
214 ResetFromTransit(sp.UUID);
215
213 sp.ControllingClient.SendTeleportFailed("Internal error"); 216 sp.ControllingClient.SendTeleportFailed("Internal error");
214 } 217 }
215 } 218 }
@@ -384,7 +387,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
384 return; 387 return;
385 } 388 }
386 389
387 if (IsInTransit(sp.UUID)) // Avie is already on the way. Caller shouldn't do this. 390 if (!SetInTransit(sp.UUID)) // Avie is already on the way. Caller shouldn't do this.
388 { 391 {
389 m_log.DebugFormat( 392 m_log.DebugFormat(
390 "[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2} ({3}) {4}/{5} - agent is already in transit.", 393 "[ENTITY TRANSFER MODULE]: Ignoring teleport request of {0} {1} to {2} ({3}) {4}/{5} - agent is already in transit.",
@@ -432,8 +435,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
432 if (!m_aScene.SimulationService.QueryAccess(finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out version, out reason)) 435 if (!m_aScene.SimulationService.QueryAccess(finalDestination, sp.ControllingClient.AgentId, Vector3.Zero, out version, out reason))
433 { 436 {
434 sp.ControllingClient.SendTeleportFailed("Teleport failed: " + reason); 437 sp.ControllingClient.SendTeleportFailed("Teleport failed: " + reason);
438 ResetFromTransit(sp.UUID);
439
435 return; 440 return;
436 } 441 }
442
437 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version); 443 m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Destination is running version {0}", version);
438 444
439 sp.ControllingClient.SendTeleportStart(teleportFlags); 445 sp.ControllingClient.SendTeleportStart(teleportFlags);
@@ -473,13 +479,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
473 bool logout = false; 479 bool logout = false;
474 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout)) 480 if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout))
475 { 481 {
476 sp.ControllingClient.SendTeleportFailed(String.Format("Teleport refused: {0}", 482 sp.ControllingClient.SendTeleportFailed(
477 reason)); 483 String.Format("Teleport refused: {0}", reason));
484 ResetFromTransit(sp.UUID);
485
478 return; 486 return;
479 } 487 }
480 488
481 // OK, it got this agent. Let's close some child agents 489 // OK, it got this agent. Let's close some child agents
482 sp.CloseChildAgents(newRegionX, newRegionY); 490 sp.CloseChildAgents(newRegionX, newRegionY);
491
483 IClientIPEndpoint ipepClient; 492 IClientIPEndpoint ipepClient;
484 if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY)) 493 if (NeedsNewAgent(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY))
485 { 494 {
@@ -516,8 +525,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
516 capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); 525 capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);
517 } 526 }
518 527
519 SetInTransit(sp.UUID);
520
521 // Let's send a full update of the agent. This is a synchronous call. 528 // Let's send a full update of the agent. This is a synchronous call.
522 AgentData agent = new AgentData(); 529 AgentData agent = new AgentData();
523 sp.CopyTo(agent); 530 sp.CopyTo(agent);
@@ -1956,25 +1963,43 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1956 return count > 0; 1963 return count > 0;
1957 } 1964 }
1958 1965
1959 protected void SetInTransit(UUID id) 1966 /// <summary>
1967 /// Set that an agent is in the process of being teleported.
1968 /// </summary>
1969 /// <param name='id'>The ID of the agent being teleported</param>
1970 /// <returns>true if the agent was not already in transit, false if it was</returns>
1971 protected bool SetInTransit(UUID id)
1960 { 1972 {
1961 lock (m_agentsInTransit) 1973 lock (m_agentsInTransit)
1962 { 1974 {
1963 if (!m_agentsInTransit.Contains(id)) 1975 if (!m_agentsInTransit.Contains(id))
1976 {
1964 m_agentsInTransit.Add(id); 1977 m_agentsInTransit.Add(id);
1978 return true;
1979 }
1965 } 1980 }
1981
1982 return false;
1966 } 1983 }
1967 1984
1985 /// <summary>
1986 /// Show whether the given agent is being teleported.
1987 /// </summary>
1988 /// <returns>true if the agent is in the process of being teleported, false otherwise.</returns>
1989 /// <param name='id'>The agent ID</para></param>
1968 protected bool IsInTransit(UUID id) 1990 protected bool IsInTransit(UUID id)
1969 { 1991 {
1970 lock (m_agentsInTransit) 1992 lock (m_agentsInTransit)
1971 { 1993 return m_agentsInTransit.Contains(id);
1972 if (m_agentsInTransit.Contains(id))
1973 return true;
1974 }
1975 return false;
1976 } 1994 }
1977 1995
1996 /// <summary>
1997 /// Set that an agent is no longer being teleported.
1998 /// </summary>
1999 /// <returns></returns>
2000 /// <param name='id'>
2001 /// true if the agent was flagged as being teleported when this method was called, false otherwise
2002 /// </param>
1978 protected bool ResetFromTransit(UUID id) 2003 protected bool ResetFromTransit(UUID id)
1979 { 2004 {
1980 lock (m_agentsInTransit) 2005 lock (m_agentsInTransit)
@@ -1985,6 +2010,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1985 return true; 2010 return true;
1986 } 2011 }
1987 } 2012 }
2013
1988 return false; 2014 return false;
1989 } 2015 }
1990 2016