aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2013-09-02 19:15:10 +0100
committerJustin Clark-Casey (justincc)2013-09-02 19:15:10 +0100
commit857f24a5e2b59072ad4d987d5e64318f5249c7e7 (patch)
treefb2bdcae26a3eb6290ed9a587cf729172bf4f8a2
parentComment out warning about agent updating without valid session ID for now. (diff)
downloadopensim-SC_OLD-857f24a5e2b59072ad4d987d5e64318f5249c7e7.zip
opensim-SC_OLD-857f24a5e2b59072ad4d987d5e64318f5249c7e7.tar.gz
opensim-SC_OLD-857f24a5e2b59072ad4d987d5e64318f5249c7e7.tar.bz2
opensim-SC_OLD-857f24a5e2b59072ad4d987d5e64318f5249c7e7.tar.xz
Fix bug where users teleporting to non-neighbour regions could continue to hear chat from their source region for some time after teleport completion.
This occurs on v2 teleport since the source region now waits 15 secs before closing the old child agent, which could still receive chat. This commit introduces a ScenePresenceState.PreClose which is set before the wait, so that ChatModule can check for ScenePresenceState.Running. This was theoretically also an issue on v1 teleport but since the pause before close was only 2 secs there, it was not noticed.
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs15
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs7
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs59
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs15
5 files changed, 85 insertions, 15 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
index 626932f..b3b0b8a 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs
@@ -76,7 +76,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
76 } 76 }
77 77
78 [Test] 78 [Test]
79 public void AddForClient() 79 public void TestAddForClient()
80 { 80 {
81 TestHelpers.InMethod(); 81 TestHelpers.InMethod();
82// log4net.Config.XmlConfigurator.Configure(); 82// log4net.Config.XmlConfigurator.Configure();
@@ -88,7 +88,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests
88 } 88 }
89 89
90 [Test] 90 [Test]
91 public void RemoveForClient() 91 public void TestRemoveForClient()
92 { 92 {
93 TestHelpers.InMethod(); 93 TestHelpers.InMethod();
94// TestHelpers.EnableLogging(); 94// TestHelpers.EnableLogging();
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index 58f747b..5229c08 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
@@ -326,15 +326,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
326 UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type, 326 UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type,
327 string message, ChatSourceType src, bool ignoreDistance) 327 string message, ChatSourceType src, bool ignoreDistance)
328 { 328 {
329 Vector3 fromRegionPos = fromPos + regionPos; 329 if (presence.LifecycleState != ScenePresenceState.Running)
330 Vector3 toRegionPos = presence.AbsolutePosition + 330 return false;
331 new Vector3(presence.Scene.RegionInfo.RegionLocX * Constants.RegionSize,
332 presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
333
334 int dis = (int)Util.GetDistanceTo(toRegionPos, fromRegionPos);
335 331
336 if (!ignoreDistance) 332 if (!ignoreDistance)
337 { 333 {
334 Vector3 fromRegionPos = fromPos + regionPos;
335 Vector3 toRegionPos = presence.AbsolutePosition +
336 new Vector3(presence.Scene.RegionInfo.RegionLocX * Constants.RegionSize,
337 presence.Scene.RegionInfo.RegionLocY * Constants.RegionSize, 0);
338
339 int dis = (int)Util.GetDistanceTo(toRegionPos, fromRegionPos);
340
338 if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance || 341 if (type == ChatTypeEnum.Whisper && dis > m_whisperdistance ||
339 type == ChatTypeEnum.Say && dis > m_saydistance || 342 type == ChatTypeEnum.Say && dis > m_saydistance ||
340 type == ChatTypeEnum.Shout && dis > m_shoutdistance) 343 type == ChatTypeEnum.Shout && dis > m_shoutdistance)
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index 8950516..4219254 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -920,6 +920,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
920 920
921 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) 921 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
922 { 922 {
923 if (!sp.Scene.IncomingPreCloseAgent(sp))
924 return;
925
923 // We need to delay here because Imprudence viewers, unlike v1 or v3, have a short (<200ms, <500ms) delay before 926 // We need to delay here because Imprudence viewers, unlike v1 or v3, have a short (<200ms, <500ms) delay before
924 // they regard the new region as the current region after receiving the AgentMovementComplete 927 // they regard the new region as the current region after receiving the AgentMovementComplete
925 // response. If close is sent before then, it will cause the viewer to quit instead. 928 // response. If close is sent before then, it will cause the viewer to quit instead.
@@ -1082,6 +1085,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1082 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone 1085 // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
1083 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) 1086 if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
1084 { 1087 {
1088 if (!sp.Scene.IncomingPreCloseAgent(sp))
1089 return;
1090
1085 // RED ALERT!!!! 1091 // RED ALERT!!!!
1086 // PLEASE DO NOT DECREASE THIS WAIT TIME UNDER ANY CIRCUMSTANCES. 1092 // PLEASE DO NOT DECREASE THIS WAIT TIME UNDER ANY CIRCUMSTANCES.
1087 // THE VIEWERS SEEM TO NEED SOME TIME AFTER RECEIVING MoveAgentIntoRegion 1093 // THE VIEWERS SEEM TO NEED SOME TIME AFTER RECEIVING MoveAgentIntoRegion
@@ -1095,6 +1101,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1095 // then this will be handled in IncomingCloseAgent under lock conditions 1101 // then this will be handled in IncomingCloseAgent under lock conditions
1096 m_log.DebugFormat( 1102 m_log.DebugFormat(
1097 "[ENTITY TRANSFER MODULE]: Closing agent {0} in {1} after teleport", sp.Name, Scene.Name); 1103 "[ENTITY TRANSFER MODULE]: Closing agent {0} in {1} after teleport", sp.Name, Scene.Name);
1104
1098 sp.Scene.IncomingCloseAgent(sp.UUID, false); 1105 sp.Scene.IncomingCloseAgent(sp.UUID, false);
1099 } 1106 }
1100 else 1107 else
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 005c9b9..2a21a4c 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -3695,10 +3695,13 @@ namespace OpenSim.Region.Framework.Scenes
3695 3695
3696 // We need to ensure that we are not already removing the scene presence before we ask it not to be 3696 // We need to ensure that we are not already removing the scene presence before we ask it not to be
3697 // closed. 3697 // closed.
3698 if (sp != null && sp.IsChildAgent && sp.LifecycleState == ScenePresenceState.Running) 3698 if (sp != null && sp.IsChildAgent
3699 && (sp.LifecycleState == ScenePresenceState.Running
3700 || sp.LifecycleState == ScenePresenceState.PreRemove))
3699 { 3701 {
3700 m_log.DebugFormat( 3702 m_log.DebugFormat(
3701 "[SCENE]: Reusing existing child scene presence for {0} in {1}", sp.Name, Name); 3703 "[SCENE]: Reusing existing child scene presence for {0}, state {1} in {2}",
3704 sp.Name, sp.LifecycleState, Name);
3702 3705
3703 // In the case where, for example, an A B C D region layout, an avatar may 3706 // In the case where, for example, an A B C D region layout, an avatar may
3704 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. When C 3707 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. When C
@@ -3720,6 +3723,8 @@ namespace OpenSim.Region.Framework.Scenes
3720// } 3723// }
3721// else if (EntityTransferModule.IsInTransit(sp.UUID)) 3724// else if (EntityTransferModule.IsInTransit(sp.UUID))
3722 3725
3726 sp.LifecycleState = ScenePresenceState.Running;
3727
3723 if (EntityTransferModule.IsInTransit(sp.UUID)) 3728 if (EntityTransferModule.IsInTransit(sp.UUID))
3724 { 3729 {
3725 sp.DoNotCloseAfterTeleport = true; 3730 sp.DoNotCloseAfterTeleport = true;
@@ -4441,6 +4446,50 @@ namespace OpenSim.Region.Framework.Scenes
4441 } 4446 }
4442 4447
4443 /// <summary> 4448 /// <summary>
4449 /// Tell a single agent to prepare to close.
4450 /// </summary>
4451 /// <remarks>
4452 /// This should only be called if we may close the agent but there will be some delay in so doing. Meant for
4453 /// internal use - other callers should almost certainly called IncomingCloseAgent().
4454 /// </remarks>
4455 /// <param name="sp"></param>
4456 /// <returns>true if pre-close state notification was successful. false if the agent
4457 /// was not in a state where it could transition to pre-close.</returns>
4458 public bool IncomingPreCloseAgent(ScenePresence sp)
4459 {
4460 lock (m_removeClientLock)
4461 {
4462 // We need to avoid a race condition where in, for example, an A B C D region layout, an avatar may
4463 // teleport from A -> D, but then -> C before A has asked B to close its old child agent. We do not
4464 // want to obey this close since C may have renewed the child agent lease on B.
4465 if (sp.DoNotCloseAfterTeleport)
4466 {
4467 m_log.DebugFormat(
4468 "[SCENE]: Not pre-closing {0} agent {1} in {2} since another simulator has re-established the child connection",
4469 sp.IsChildAgent ? "child" : "root", sp.Name, Name);
4470
4471 // Need to reset the flag so that a subsequent close after another teleport can succeed.
4472 sp.DoNotCloseAfterTeleport = false;
4473
4474 return false;
4475 }
4476
4477 if (sp.LifecycleState != ScenePresenceState.Running)
4478 {
4479 m_log.DebugFormat(
4480 "[SCENE]: Called IncomingPreCloseAgent() for {0} in {1} but presence is already in state {2}",
4481 sp.Name, Name, sp.LifecycleState);
4482
4483 return false;
4484 }
4485
4486 sp.LifecycleState = ScenePresenceState.PreRemove;
4487
4488 return true;
4489 }
4490 }
4491
4492 /// <summary>
4444 /// Tell a single agent to disconnect from the region. 4493 /// Tell a single agent to disconnect from the region.
4445 /// </summary> 4494 /// </summary>
4446 /// <param name="agentID"></param> 4495 /// <param name="agentID"></param>
@@ -4459,16 +4508,16 @@ namespace OpenSim.Region.Framework.Scenes
4459 if (sp == null) 4508 if (sp == null)
4460 { 4509 {
4461 m_log.DebugFormat( 4510 m_log.DebugFormat(
4462 "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in {1}", 4511 "[SCENE]: Called IncomingCloseAgent() with agent ID {0} but no such presence is in {1}",
4463 agentID, Name); 4512 agentID, Name);
4464 4513
4465 return false; 4514 return false;
4466 } 4515 }
4467 4516
4468 if (sp.LifecycleState != ScenePresenceState.Running) 4517 if (sp.LifecycleState != ScenePresenceState.Running && sp.LifecycleState != ScenePresenceState.PreRemove)
4469 { 4518 {
4470 m_log.DebugFormat( 4519 m_log.DebugFormat(
4471 "[SCENE]: Called RemoveClient() for {0} in {1} but presence is already in state {2}", 4520 "[SCENE]: Called IncomingCloseAgent() for {0} in {1} but presence is already in state {2}",
4472 sp.Name, Name, sp.LifecycleState); 4521 sp.Name, Name, sp.LifecycleState);
4473 4522
4474 return false; 4523 return false;
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs b/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs
index dc3a212..cae7fe5 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresenceStateMachine.cs
@@ -37,7 +37,8 @@ namespace OpenSim.Region.Framework.Scenes
37 /// This is a state machine. 37 /// This is a state machine.
38 /// 38 ///
39 /// [Entry] => Running 39 /// [Entry] => Running
40 /// Running => Removing 40 /// Running => PreRemove, Removing
41 /// PreRemove => Running, Removing
41 /// Removing => Removed 42 /// Removing => Removed
42 /// 43 ///
43 /// All other methods should only see the scene presence in running state - this is the normal operational state 44 /// All other methods should only see the scene presence in running state - this is the normal operational state
@@ -46,6 +47,7 @@ namespace OpenSim.Region.Framework.Scenes
46 public enum ScenePresenceState 47 public enum ScenePresenceState
47 { 48 {
48 Running, // Normal operation state. The scene presence is available. 49 Running, // Normal operation state. The scene presence is available.
50 PreRemove, // The presence is due to be removed but can still be returning to running.
49 Removing, // The presence is in the process of being removed from the scene via Scene.RemoveClient. 51 Removing, // The presence is in the process of being removed from the scene via Scene.RemoveClient.
50 Removed, // The presence has been removed from the scene and is effectively dead. 52 Removed, // The presence has been removed from the scene and is effectively dead.
51 // There is no exit from this state. 53 // There is no exit from this state.
@@ -80,8 +82,17 @@ namespace OpenSim.Region.Framework.Scenes
80 82
81 lock (this) 83 lock (this)
82 { 84 {
83 if (newState == ScenePresenceState.Removing && m_state == ScenePresenceState.Running) 85 if (newState == m_state)
86 return;
87 else if (newState == ScenePresenceState.Running && m_state == ScenePresenceState.PreRemove)
84 transitionOkay = true; 88 transitionOkay = true;
89 else if (newState == ScenePresenceState.PreRemove && m_state == ScenePresenceState.Running)
90 transitionOkay = true;
91 else if (newState == ScenePresenceState.Removing)
92 {
93 if (m_state == ScenePresenceState.Running || m_state == ScenePresenceState.PreRemove)
94 transitionOkay = true;
95 }
85 else if (newState == ScenePresenceState.Removed && m_state == ScenePresenceState.Removing) 96 else if (newState == ScenePresenceState.Removed && m_state == ScenePresenceState.Removing)
86 transitionOkay = true; 97 transitionOkay = true;
87 } 98 }