From c42fe6c159d49535888937c3f219e028eb755efa Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Tue, 14 Aug 2012 21:44:06 +0100
Subject: Prevent race conditions when one thread removes an NPC SP before
 another thread has retreived it after checking whether the NPC exists.

---
 .../Region/OptionalModules/World/NPC/NPCModule.cs  | 64 ++++++++++------------
 .../Shared/Api/Implementation/OSSL_Api.cs          | 25 +++++++--
 2 files changed, 50 insertions(+), 39 deletions(-)

diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
index 1e85fb4..3f25bcf 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
@@ -176,16 +176,17 @@ namespace OpenSim.Region.OptionalModules.World.NPC
                 if (m_avatars.ContainsKey(agentID))
                 {
                     ScenePresence sp;
-                    scene.TryGetScenePresence(agentID, out sp);
-
-                    m_log.DebugFormat(
-                        "[NPC MODULE]: Moving {0} to {1} in {2}, noFly {3}, landAtTarget {4}",
-                        sp.Name, pos, scene.RegionInfo.RegionName, noFly, landAtTarget);
-
-                    sp.MoveToTarget(pos, noFly, landAtTarget);
-                    sp.SetAlwaysRun = running;
-
-                    return true;
+                    if (scene.TryGetScenePresence(agentID, out sp))
+                    {
+                        m_log.DebugFormat(
+                            "[NPC MODULE]: Moving {0} to {1} in {2}, noFly {3}, landAtTarget {4}",
+                            sp.Name, pos, scene.RegionInfo.RegionName, noFly, landAtTarget);
+
+                        sp.MoveToTarget(pos, noFly, landAtTarget);
+                        sp.SetAlwaysRun = running;
+    
+                        return true;
+                    }
                 }
             }
 
@@ -199,12 +200,13 @@ namespace OpenSim.Region.OptionalModules.World.NPC
                 if (m_avatars.ContainsKey(agentID))
                 {
                     ScenePresence sp;
-                    scene.TryGetScenePresence(agentID, out sp);
-
-                    sp.Velocity = Vector3.Zero;
-                    sp.ResetMoveToTarget();
+                    if (scene.TryGetScenePresence(agentID, out sp))
+                    {
+                        sp.Velocity = Vector3.Zero;
+                        sp.ResetMoveToTarget();
 
-                    return true;
+                        return true;
+                    }
                 }
             }
 
@@ -222,9 +224,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC
             {
                 if (m_avatars.ContainsKey(agentID))
                 {
-                    ScenePresence sp;
-                    scene.TryGetScenePresence(agentID, out sp);
-
                     m_avatars[agentID].Say(channel, text);
 
                     return true;
@@ -240,9 +239,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC
             {
                 if (m_avatars.ContainsKey(agentID))
                 {
-                    ScenePresence sp;
-                    scene.TryGetScenePresence(agentID, out sp);
-
                     m_avatars[agentID].Shout(channel, text);
 
                     return true;
@@ -259,11 +255,13 @@ namespace OpenSim.Region.OptionalModules.World.NPC
                 if (m_avatars.ContainsKey(agentID))
                 {
                     ScenePresence sp;
-                    scene.TryGetScenePresence(agentID, out sp);
-                    sp.HandleAgentRequestSit(m_avatars[agentID], agentID, partID, Vector3.Zero);
-//                    sp.HandleAgentSit(m_avatars[agentID], agentID);
-
-                    return true;
+                    if (scene.TryGetScenePresence(agentID, out sp))
+                    {
+                        sp.HandleAgentRequestSit(m_avatars[agentID], agentID, partID, Vector3.Zero);
+    //                    sp.HandleAgentSit(m_avatars[agentID], agentID);
+    
+                        return true;
+                    }
                 }
             }
 
@@ -276,9 +274,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC
             {
                 if (m_avatars.ContainsKey(agentID))
                 {
-                    ScenePresence sp;
-                    scene.TryGetScenePresence(agentID, out sp);
-
                     m_avatars[agentID].Whisper(channel, text);
 
                     return true;
@@ -295,10 +290,12 @@ namespace OpenSim.Region.OptionalModules.World.NPC
                 if (m_avatars.ContainsKey(agentID))
                 {
                     ScenePresence sp;
-                    scene.TryGetScenePresence(agentID, out sp);
-                    sp.StandUp();
+                    if (scene.TryGetScenePresence(agentID, out sp))
+                    {
+                        sp.StandUp();
 
-                    return true;
+                        return true;
+                    }
                 }
             }
 
@@ -311,6 +308,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
             {
                 if (m_avatars.ContainsKey(agentID))
                     return m_avatars[agentID].Touch(objectID);
+
                 return false;
             }
         }
@@ -321,9 +319,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
             {
                 NPCAvatar av;
                 if (m_avatars.TryGetValue(agentID, out av))
-                {
                     return av.OwnerID;
-                }
             }
 
             return UUID.Zero;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index bcd1a6f..859ee93 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -2434,8 +2434,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                 if (!npcModule.CheckPermissions(npcId, m_host.OwnerID))
                     return new LSL_Vector(0, 0, 0);
 
-                Vector3 pos = World.GetScenePresence(npcId).AbsolutePosition;
-                return new LSL_Vector(pos.X, pos.Y, pos.Z);
+                ScenePresence sp = World.GetScenePresence(npcId);
+
+                if (sp != null)
+                {
+                    Vector3 pos = sp.AbsolutePosition;
+                    return new LSL_Vector(pos.X, pos.Y, pos.Z);
+                }
             }
 
             return new LSL_Vector(0, 0, 0);
@@ -2503,9 +2508,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                     return new LSL_Rotation(Quaternion.Identity.X, Quaternion.Identity.Y, Quaternion.Identity.Z, Quaternion.Identity.W);
 
                 ScenePresence sp = World.GetScenePresence(npcId);
-                Quaternion rot = sp.Rotation;
 
-                return new LSL_Rotation(rot.X, rot.Y, rot.Z, rot.W);
+                if (sp != null)
+                {
+                    Quaternion rot = sp.Rotation;
+                    return new LSL_Rotation(rot.X, rot.Y, rot.Z, rot.W);
+                }
             }
 
             return new LSL_Rotation(Quaternion.Identity.X, Quaternion.Identity.Y, Quaternion.Identity.Z, Quaternion.Identity.W);
@@ -2527,7 +2535,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                     return;
 
                 ScenePresence sp = World.GetScenePresence(npcId);
-                sp.Rotation = LSL_Api.Rot2Quaternion(rotation);
+
+                if (sp != null)
+                    sp.Rotation = LSL_Api.Rot2Quaternion(rotation);
             }
         }
 
@@ -2689,6 +2699,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
         {
             CheckThreatLevel(ThreatLevel.High, "osNpcTouch");
             m_host.AddScriptLPS(1);
+            
             INPCModule module = World.RequestModuleInterface<INPCModule>();
             int linkNum = link_num.value;
             if (module != null || (linkNum < 0 && linkNum != ScriptBaseClass.LINK_THIS))
@@ -2696,12 +2707,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                 UUID npcId;
                 if (!UUID.TryParse(npcLSL_Key, out npcId) || !module.CheckPermissions(npcId, m_host.OwnerID))
                     return;
+
                 SceneObjectPart part = null;
                 UUID objectId;
                 if (UUID.TryParse(LSL_String.ToString(object_key), out objectId))
                     part = World.GetSceneObjectPart(objectId);
+
                 if (part == null)
                     return;
+
                 if (linkNum != ScriptBaseClass.LINK_THIS)
                 {
                     if (linkNum == 0 || linkNum == ScriptBaseClass.LINK_ROOT)
@@ -2716,6 +2730,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
                             return;
                     }
                 }
+
                 module.Touch(npcId, part.UUID);
             }
         }
-- 
cgit v1.1