aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2011-11-02 18:12:12 +0000
committerJustin Clark-Casey (justincc)2011-11-02 18:25:03 +0000
commit03993d0b14599358ac30a001cebd5b2145881c65 (patch)
treebb875b81821c0dff0bf195d530ad2f2dda96b2d0
parentCatch any exceptions exiting the top of the robust console, as we already do ... (diff)
downloadopensim-SC-03993d0b14599358ac30a001cebd5b2145881c65.zip
opensim-SC-03993d0b14599358ac30a001cebd5b2145881c65.tar.gz
opensim-SC-03993d0b14599358ac30a001cebd5b2145881c65.tar.bz2
opensim-SC-03993d0b14599358ac30a001cebd5b2145881c65.tar.xz
Fix race condition that would sometimes send or save appearance for the wrong avatar.
In AvatarFactoryModule.HandleAppearanceUpdateTimer(), we loop through appearance save and send requests and dispatch via a FireAndForget thread. If there was more than one request in the save or send queue, then this led to a subtle race condition where the foreach loop would load in the next KeyValuePair before the thread was dispatched. This gave the thread the wrong avatar ID, leaving some avatar appearance cloudy since appearance data was never sent. This change loads the fields into local references so that this doesn't happen.
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs28
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs5
2 files changed, 24 insertions, 9 deletions
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index 236a47c..07d1cb3 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -169,6 +169,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
169 169
170 public bool SendAppearance(UUID agentId) 170 public bool SendAppearance(UUID agentId)
171 { 171 {
172// m_log.DebugFormat("[AVFACTORY]: Sending appearance for {0}", agentId);
173
172 ScenePresence sp = m_scene.GetScenePresence(agentId); 174 ScenePresence sp = m_scene.GetScenePresence(agentId);
173 if (sp == null) 175 if (sp == null)
174 { 176 {
@@ -257,7 +259,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
257 /// </summary> 259 /// </summary>
258 public void QueueAppearanceSend(UUID agentid) 260 public void QueueAppearanceSend(UUID agentid)
259 { 261 {
260 // m_log.WarnFormat("[AVFACTORY]: Queue appearance send for {0}", agentid); 262// m_log.DebugFormat("[AVFACTORY]: Queue appearance send for {0}", agentid);
261 263
262 // 10000 ticks per millisecond, 1000 milliseconds per second 264 // 10000 ticks per millisecond, 1000 milliseconds per second
263 long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 1000 * 10000); 265 long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 1000 * 10000);
@@ -393,10 +395,17 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
393 Dictionary<UUID, long> sends = new Dictionary<UUID, long>(m_sendqueue); 395 Dictionary<UUID, long> sends = new Dictionary<UUID, long>(m_sendqueue);
394 foreach (KeyValuePair<UUID, long> kvp in sends) 396 foreach (KeyValuePair<UUID, long> kvp in sends)
395 { 397 {
396 if (kvp.Value < now) 398 // We have to load the key and value into local parameters to avoid a race condition if we loop
399 // around and load kvp with a different value before FireAndForget has launched its thread.
400 UUID avatarID = kvp.Key;
401 long sendTime = kvp.Value;
402
403// m_log.DebugFormat("[AVFACTORY]: Handling queued appearance updates for {0}, update delta to now is {1}", avatarID, sendTime - now);
404
405 if (sendTime < now)
397 { 406 {
398 Util.FireAndForget(delegate(object o) { SendAppearance(kvp.Key); }); 407 Util.FireAndForget(o => SendAppearance(avatarID));
399 m_sendqueue.Remove(kvp.Key); 408 m_sendqueue.Remove(avatarID);
400 } 409 }
401 } 410 }
402 } 411 }
@@ -406,10 +415,15 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
406 Dictionary<UUID, long> saves = new Dictionary<UUID, long>(m_savequeue); 415 Dictionary<UUID, long> saves = new Dictionary<UUID, long>(m_savequeue);
407 foreach (KeyValuePair<UUID, long> kvp in saves) 416 foreach (KeyValuePair<UUID, long> kvp in saves)
408 { 417 {
409 if (kvp.Value < now) 418 // We have to load the key and value into local parameters to avoid a race condition if we loop
419 // around and load kvp with a different value before FireAndForget has launched its thread.
420 UUID avatarID = kvp.Key;
421 long sendTime = kvp.Value;
422
423 if (sendTime < now)
410 { 424 {
411 Util.FireAndForget(delegate(object o) { SaveAppearance(kvp.Key); }); 425 Util.FireAndForget(o => SaveAppearance(avatarID));
412 m_savequeue.Remove(kvp.Key); 426 m_savequeue.Remove(avatarID);
413 } 427 }
414 } 428 }
415 } 429 }
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 29966f9..3e3fb0f 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -2628,7 +2628,8 @@ namespace OpenSim.Region.Framework.Scenes
2628 /// </summary> 2628 /// </summary>
2629 public void SendAppearanceToAllOtherAgents() 2629 public void SendAppearanceToAllOtherAgents()
2630 { 2630 {
2631 //m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherAgents: {0} ({1})", Name, UUID); 2631// m_log.DebugFormat("[SCENE PRESENCE] SendAppearanceToAllOtherAgents: {0} {1}", Name, UUID);
2632
2632 // only send update from root agents to other clients; children are only "listening posts" 2633 // only send update from root agents to other clients; children are only "listening posts"
2633 if (IsChildAgent) 2634 if (IsChildAgent)
2634 { 2635 {
@@ -2656,7 +2657,7 @@ namespace OpenSim.Region.Framework.Scenes
2656 /// </summary> 2657 /// </summary>
2657 public void SendOtherAgentsAppearanceToMe() 2658 public void SendOtherAgentsAppearanceToMe()
2658 { 2659 {
2659 //m_log.DebugFormat("[SCENE PRESENCE] SendOtherAgentsAppearanceToMe: {0} ({1})", Name, UUID); 2660// m_log.DebugFormat("[SCENE PRESENCE] SendOtherAgentsAppearanceToMe: {0} {1}", Name, UUID);
2660 2661
2661 int count = 0; 2662 int count = 0;
2662 m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence) 2663 m_scene.ForEachRootScenePresence(delegate(ScenePresence scenePresence)