diff options
author | Justin Clark-Casey (justincc) | 2012-05-14 18:36:26 +0100 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2012-05-14 18:36:26 +0100 |
commit | c2aa3b90d9d367bcaeba93352ef6b0f513e663f7 (patch) | |
tree | da532e0b514f7f7b143db0a7f9cc0731ae02112f | |
parent | Merge branch 'master' of ssh://opensimulator.org/var/git/opensim (diff) | |
download | opensim-SC_OLD-c2aa3b90d9d367bcaeba93352ef6b0f513e663f7.zip opensim-SC_OLD-c2aa3b90d9d367bcaeba93352ef6b0f513e663f7.tar.gz opensim-SC_OLD-c2aa3b90d9d367bcaeba93352ef6b0f513e663f7.tar.bz2 opensim-SC_OLD-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.
-rw-r--r-- | OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | 48 |
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 | ||