From 8031f8ec09df4f654c86a9c7bc498664f7b9d9dc Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Thu, 26 Aug 2010 00:08:53 +0100 Subject: Improve consistency of locking for SOG.m_parts in order to avoid race conditions in linking and unlinking --- .../Shared/Api/Implementation/LSL_Api.cs | 100 +++++++++++++-------- OpenSim/Region/ScriptEngine/Shared/Helpers.cs | 11 ++- 2 files changed, 68 insertions(+), 43 deletions(-) (limited to 'OpenSim/Region/ScriptEngine/Shared') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 21604d0..af42dae 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -235,7 +235,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { case ScriptBaseClass.LINK_SET: if (m_host.ParentGroup != null) - return new List(m_host.ParentGroup.Children.Values); + { + lock (m_host.ParentGroup.Children) + return new List(m_host.ParentGroup.Children.Values); + } return ret; case ScriptBaseClass.LINK_ROOT: @@ -250,7 +253,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case ScriptBaseClass.LINK_ALL_OTHERS: if (m_host.ParentGroup == null) return new List(); - ret = new List(m_host.ParentGroup.Children.Values); + + lock (m_host.ParentGroup.Children) + ret = new List(m_host.ParentGroup.Children.Values); + if (ret.Contains(m_host)) ret.Remove(m_host); return ret; @@ -258,7 +264,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case ScriptBaseClass.LINK_ALL_CHILDREN: if (m_host.ParentGroup == null) return new List(); - ret = new List(m_host.ParentGroup.Children.Values); + + lock (m_host.ParentGroup.Children) + ret = new List(m_host.ParentGroup.Children.Values); + if (ret.Contains(m_host.ParentGroup.RootPart)) ret.Remove(m_host.ParentGroup.RootPart); return ret; @@ -1178,12 +1187,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (group == null) return; bool allow = true; - foreach (SceneObjectPart part in group.Children.Values) + + lock (group.Children) { - if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys) + foreach (SceneObjectPart part in group.Children.Values) { - allow = false; - break; + if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys) + { + allow = false; + break; + } } } @@ -3492,7 +3505,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - if (m_host.ParentGroup.Children.Count > 1) + if (m_host.ParentGroup.PrimCount > 1) { return m_host.LinkNum; } @@ -3604,15 +3617,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case ScriptBaseClass.LINK_ALL_OTHERS: case ScriptBaseClass.LINK_ALL_CHILDREN: case ScriptBaseClass.LINK_THIS: - foreach (SceneObjectPart part in parentPrim.Children.Values) + lock (parentPrim.Children) { - if (part.UUID != m_host.UUID) + foreach (SceneObjectPart part in parentPrim.Children.Values) { - childPrim = part; - break; + if (part.UUID != m_host.UUID) + { + childPrim = part; + break; + } } + break; } - break; default: childPrim = parentPrim.GetLinkNumPart(linknum); if (childPrim.UUID == m_host.UUID) @@ -3623,27 +3639,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (linknum == ScriptBaseClass.LINK_ROOT) { // Restructuring Multiple Prims. - List parts = new List(parentPrim.Children.Values); - parts.Remove(parentPrim.RootPart); - foreach (SceneObjectPart part in parts) - { - parentPrim.DelinkFromGroup(part.LocalId, true); - } - parentPrim.HasGroupChanged = true; - parentPrim.ScheduleGroupForFullUpdate(); - parentPrim.TriggerScriptChangedEvent(Changed.LINK); - - if (parts.Count > 0) + lock (parentPrim.Children) { - SceneObjectPart newRoot = parts[0]; - parts.Remove(newRoot); + List parts = new List(parentPrim.Children.Values); + parts.Remove(parentPrim.RootPart); foreach (SceneObjectPart part in parts) { - part.UpdateFlag = 0; - newRoot.ParentGroup.LinkToGroup(part.ParentGroup); + parentPrim.DelinkFromGroup(part.LocalId, true); + } + parentPrim.HasGroupChanged = true; + parentPrim.ScheduleGroupForFullUpdate(); + parentPrim.TriggerScriptChangedEvent(Changed.LINK); + + if (parts.Count > 0) + { + SceneObjectPart newRoot = parts[0]; + parts.Remove(newRoot); + foreach (SceneObjectPart part in parts) + { + part.UpdateFlag = 0; + newRoot.ParentGroup.LinkToGroup(part.ParentGroup); + } + newRoot.ParentGroup.HasGroupChanged = true; + newRoot.ParentGroup.ScheduleGroupForFullUpdate(); } - newRoot.ParentGroup.HasGroupChanged = true; - newRoot.ParentGroup.ScheduleGroupForFullUpdate(); } } else @@ -3665,16 +3684,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (parentPrim.RootPart.AttachmentPoint != 0) return; // Fail silently if attached - List parts = new List(parentPrim.Children.Values); - parts.Remove(parentPrim.RootPart); - - foreach (SceneObjectPart part in parts) + lock (parentPrim.Children) { - parentPrim.DelinkFromGroup(part.LocalId, true); - parentPrim.TriggerScriptChangedEvent(Changed.LINK); + List parts = new List(parentPrim.Children.Values); + parts.Remove(parentPrim.RootPart); + + foreach (SceneObjectPart part in parts) + { + parentPrim.DelinkFromGroup(part.LocalId, true); + parentPrim.TriggerScriptChangedEvent(Changed.LINK); + } + parentPrim.HasGroupChanged = true; + parentPrim.ScheduleGroupForFullUpdate(); } - parentPrim.HasGroupChanged = true; - parentPrim.ScheduleGroupForFullUpdate(); } public LSL_String llGetLinkKey(int linknum) @@ -4200,7 +4222,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { partItemID = item.ItemID; int linkNumber = m_host.LinkNum; - if (m_host.ParentGroup.Children.Count == 1) + if (m_host.ParentGroup.PrimCount == 1) linkNumber = 0; object[] resobj = new object[] diff --git a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs index 4855d64..41501f2 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs @@ -209,12 +209,15 @@ namespace OpenSim.Region.ScriptEngine.Shared else Type = 0x02; // Passive - foreach (SceneObjectPart p in part.ParentGroup.Children.Values) + lock (part.ParentGroup.Children) { - if (p.Inventory.ContainsScripts()) + foreach (SceneObjectPart p in part.ParentGroup.Children.Values) { - Type |= 0x08; // Scripted - break; + if (p.Inventory.ContainsScripts()) + { + Type |= 0x08; // Scripted + break; + } } } -- cgit v1.1