From 01f70de2ea562f78991084be01a83295f8f2be0b Mon Sep 17 00:00:00 2001 From: Justin Clarke Casey Date: Fri, 20 Feb 2009 14:04:29 +0000 Subject: * Consistently lock part.TaskInventory as pointed out in http://opensimulator.org/mantis/view.php?id=3159 * Not locking causes enumeration exceptions as described in this matis * part.TaskInventory needs to be locked for every access as it's a dictionary * Extra locking will hopefully not cause any major issues - in places where the enumeration of the dictionary performs other lock or long running operations, the dictionary is cloned instead --- OpenSim/Framework/TaskInventoryDictionary.cs | 4 +- .../World/Archiver/ArchiveReadRequest.cs | 19 +- .../Framework/Scenes/Hypergrid/HGAssetMapper.cs | 7 +- OpenSim/Region/Framework/Scenes/SceneObjectPart.cs | 34 +- OpenSim/Region/Framework/Scenes/UuidGatherer.cs | 6 +- .../Shared/Api/Implementation/LSL_Api.cs | 517 ++++++++++++++------- .../ScriptEngine/Shared/Instance/ScriptInstance.cs | 28 +- 7 files changed, 414 insertions(+), 201 deletions(-) diff --git a/OpenSim/Framework/TaskInventoryDictionary.cs b/OpenSim/Framework/TaskInventoryDictionary.cs index 4a1aa17..defac23 100644 --- a/OpenSim/Framework/TaskInventoryDictionary.cs +++ b/OpenSim/Framework/TaskInventoryDictionary.cs @@ -36,9 +36,9 @@ namespace OpenSim.Framework { /// /// A dictionary for task inventory. - /// - /// This class is not thread safe. Callers must synchronize on Dictionary methods. /// + /// This class is not thread safe. Callers must synchronize on Dictionary methods or Clone() this object before + /// iterating over it. public class TaskInventoryDictionary : Dictionary, ICloneable, IXmlSerializable { diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index d7ab5fd..fe1c42b 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -202,16 +202,19 @@ namespace OpenSim.Region.CoreModules.World.Archiver // Fix ownership/creator of inventory items // Not doing so results in inventory items // being no copy/no mod for everyone - TaskInventoryDictionary inv = part.TaskInventory; - foreach (KeyValuePair kvp in inv) + lock (part.TaskInventory) { - if (!ResolveUserUuid(kvp.Value.OwnerID)) + TaskInventoryDictionary inv = part.TaskInventory; + foreach (KeyValuePair kvp in inv) { - kvp.Value.OwnerID = masterAvatarId; - } - if (!ResolveUserUuid(kvp.Value.CreatorID)) - { - kvp.Value.CreatorID = masterAvatarId; + if (!ResolveUserUuid(kvp.Value.OwnerID)) + { + kvp.Value.OwnerID = masterAvatarId; + } + if (!ResolveUserUuid(kvp.Value.CreatorID)) + { + kvp.Value.CreatorID = masterAvatarId; + } } } } diff --git a/OpenSim/Region/Framework/Scenes/Hypergrid/HGAssetMapper.cs b/OpenSim/Region/Framework/Scenes/Hypergrid/HGAssetMapper.cs index 1a3c4c8..f7db908 100644 --- a/OpenSim/Region/Framework/Scenes/Hypergrid/HGAssetMapper.cs +++ b/OpenSim/Region/Framework/Scenes/Hypergrid/HGAssetMapper.cs @@ -226,9 +226,12 @@ namespace OpenSim.Region.Framework.Scenes.Hypergrid { TaskInventoryDictionary tinv = sog.RootPart.TaskInventory; - foreach (TaskInventoryItem titem in tinv.Values) + lock (tinv) { - uuids.Add(titem.AssetID, (InventoryType)titem.Type == InventoryType.Texture); + foreach (TaskInventoryItem titem in tinv.Values) + { + uuids.Add(titem.AssetID, (InventoryType)titem.Type == InventoryType.Texture); + } } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index ec3fdf1..27c22eb 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -1710,12 +1710,15 @@ if (m_shape != null) { info.AddValue("m_inventoryFileName", Inventory.GetInventoryFileName()); info.AddValue("m_folderID", UUID); info.AddValue("PhysActor", PhysActor); - + Dictionary TaskInventory_work = new Dictionary(); - foreach (UUID id in TaskInventory.Keys) + lock (TaskInventory) { - TaskInventory_work.Add(id.Guid, TaskInventory[id]); + foreach (UUID id in TaskInventory.Keys) + { + TaskInventory_work.Add(id.Guid, TaskInventory[id]); + } } info.AddValue("TaskInventory", TaskInventory_work); @@ -2166,13 +2169,16 @@ if (m_shape != null) { { //Trys to fetch sound id from prim's inventory. //Prim's inventory doesn't support non script items yet - SceneObjectPart op = this; - foreach (KeyValuePair item in op.TaskInventory) + + lock (TaskInventory) { - if (item.Value.Name == sound) + foreach (KeyValuePair item in TaskInventory) { - soundID = item.Value.ItemID; - break; + if (item.Value.Name == sound) + { + soundID = item.Value.ItemID; + break; + } } } } @@ -2486,13 +2492,15 @@ if (m_shape != null) { if (!UUID.TryParse(sound, out soundID)) { // search sound file from inventory - SceneObjectPart op = this; - foreach (KeyValuePair item in op.TaskInventory) + lock (TaskInventory) { - if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) + foreach (KeyValuePair item in TaskInventory) { - soundID = item.Value.ItemID; - break; + if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) + { + soundID = item.Value.ItemID; + break; + } } } } diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs index bc8896e..7b2fae0 100644 --- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs +++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs @@ -140,9 +140,11 @@ namespace OpenSim.Region.Framework.Scenes // If the prim is a sculpt then preserve this information too if (part.Shape.SculptTexture != UUID.Zero) assetUuids[part.Shape.SculptTexture] = 1; - + + TaskInventoryDictionary taskDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); + // Now analyze this prim's inventory items to preserve all the uuids that they reference - foreach (TaskInventoryItem tii in part.TaskInventory.Values) + foreach (TaskInventoryItem tii in taskDictionary.Values) { //m_log.DebugFormat("[ARCHIVER]: Analysing item asset type {0}", tii.Type); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 5f6ea16..7e4a5a0 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -250,12 +250,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { UUID invItemID = new UUID(); - foreach (KeyValuePair inv in m_host.TaskInventory) + lock (m_host.TaskInventory) { - if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID) + foreach (KeyValuePair inv in m_host.TaskInventory) { - invItemID = inv.Key; - break; + if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID) + { + invItemID = inv.Key; + break; + } } } @@ -265,29 +268,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api private UUID InventoryKey(string name, int type) { m_host.AddScriptLPS(1); - foreach (KeyValuePair inv in m_host.TaskInventory) + + lock (m_host.TaskInventory) { - if (inv.Value.Name == name) + foreach (KeyValuePair inv in m_host.TaskInventory) { - if (inv.Value.Type != type) - return UUID.Zero; + if (inv.Value.Name == name) + { + if (inv.Value.Type != type) + return UUID.Zero; - return inv.Value.AssetID; + return inv.Value.AssetID; + } } } + return UUID.Zero; } private UUID InventoryKey(string name) { m_host.AddScriptLPS(1); - foreach (KeyValuePair inv in m_host.TaskInventory) + + lock (m_host.TaskInventory) { - if (inv.Value.Name == name) + foreach (KeyValuePair inv in m_host.TaskInventory) { - return inv.Value.AssetID; + if (inv.Value.Name == name) + { + return inv.Value.AssetID; + } } } + return UUID.Zero; } @@ -2376,16 +2389,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); - if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) + TaskInventoryItem item = m_host.TaskInventory[invItemID]; + + lock (m_host.TaskInventory) + { + item = m_host.TaskInventory[invItemID]; + } + + if (item.PermsGranter == UUID.Zero) return 0; - if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0) + if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0) { LSLError("No permissions to give money"); return 0; } - UUID toID=new UUID(); + UUID toID = new UUID(); if (!UUID.TryParse(destination, out toID)) { @@ -2393,7 +2413,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return 0; } - IMoneyModule money=World.RequestModuleInterface(); + IMoneyModule money = World.RequestModuleInterface(); if (money == null) { @@ -2401,7 +2421,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return 0; } - bool result=money.ObjectGiveMoney(m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount); + bool result + = money.ObjectGiveMoney( + m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount); if (result) return 1; @@ -2447,8 +2469,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (dist > m_ScriptDistanceFactor * 10.0f) return; + + TaskInventoryDictionary partInventory = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); - foreach (KeyValuePair inv in m_host.TaskInventory) + foreach (KeyValuePair inv in partInventory) { if (inv.Value.Name == inventory) { @@ -2500,6 +2524,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return; } } + llSay(0, "Could not find object " + inventory); } @@ -2571,18 +2596,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llTakeControls(int controls, int accept, int pass_on) { - if (!m_host.TaskInventory.ContainsKey(InventorySelf())) + TaskInventoryItem item; + + lock (m_host.TaskInventory) { - return; + if (!m_host.TaskInventory.ContainsKey(InventorySelf())) + return; + else + item = m_host.TaskInventory[InventorySelf()]; } - - if (m_host.TaskInventory[InventorySelf()].PermsGranter != UUID.Zero) + + if (item.PermsGranter != UUID.Zero) { - ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[InventorySelf()].PermsGranter); + ScenePresence presence = World.GetScenePresence(item.PermsGranter); if (presence != null) { - if ((m_host.TaskInventory[InventorySelf()].PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0) + if ((item.PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0) { presence.RegisterControlEventsToScript(controls, accept, pass_on, m_localID, m_itemID); } @@ -2593,26 +2623,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } public void llReleaseControls() - { - m_host.AddScriptLPS(1); - - if (!m_host.TaskInventory.ContainsKey(InventorySelf())) + { + TaskInventoryItem item; + + lock (m_host.TaskInventory) { - return; + if (!m_host.TaskInventory.ContainsKey(InventorySelf())) + return; + else + item = m_host.TaskInventory[InventorySelf()]; } + + m_host.AddScriptLPS(1); - if (m_host.TaskInventory[InventorySelf()].PermsGranter != UUID.Zero) + if (item.PermsGranter != UUID.Zero) { - ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[InventorySelf()].PermsGranter); + ScenePresence presence = World.GetScenePresence(item.PermsGranter); if (presence != null) { - if ((m_host.TaskInventory[InventorySelf()].PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0) + if ((item.PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0) { // Unregister controls from Presence presence.UnRegisterControlEventsToScript(m_localID, m_itemID); // Remove Take Control permission. - m_host.TaskInventory[InventorySelf()].PermsMask &= ~ScriptBaseClass.PERMISSION_TAKE_CONTROLS; + item.PermsMask &= ~ScriptBaseClass.PERMISSION_TAKE_CONTROLS; } } } @@ -2838,16 +2873,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - UUID invItemID=InventorySelf(); + UUID invItemID = InventorySelf(); if (invItemID == UUID.Zero) return; - if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) + TaskInventoryItem item; + + lock (m_host.TaskInventory) + { + if (!m_host.TaskInventory.ContainsKey(InventorySelf())) + return; + else + item = m_host.TaskInventory[InventorySelf()]; + } + + if (item.PermsGranter == UUID.Zero) return; - if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0) + if ((item.PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0) { - ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[invItemID].PermsGranter); + ScenePresence presence = World.GetScenePresence(item.PermsGranter); if (presence != null) { @@ -2868,11 +2913,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api UUID invItemID=InventorySelf(); if (invItemID == UUID.Zero) return; + + TaskInventoryItem item; + + lock (m_host.TaskInventory) + { + if (!m_host.TaskInventory.ContainsKey(InventorySelf())) + return; + else + item = m_host.TaskInventory[InventorySelf()]; + } - if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) + if (item.PermsGranter == UUID.Zero) return; - if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0) + if ((item.PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0) { UUID animID = new UUID(); @@ -2881,7 +2936,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api animID=InventoryKey(anim); } - ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[invItemID].PermsGranter); + ScenePresence presence = World.GetScenePresence(item.PermsGranter); if (presence != null) { @@ -2929,22 +2984,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llRequestPermissions(string agent, int perm) { - UUID agentID=new UUID(); + UUID agentID = new UUID(); if (!UUID.TryParse(agent, out agentID)) return; - UUID invItemID=InventorySelf(); + UUID invItemID = InventorySelf(); if (invItemID == UUID.Zero) return; // Not in a prim? How?? + + TaskInventoryItem item; + + lock (m_host.TaskInventory) + { + item = m_host.TaskInventory[invItemID]; + } if (agentID == UUID.Zero || perm == 0) // Releasing permissions { llReleaseControls(); - m_host.TaskInventory[invItemID].PermsGranter=UUID.Zero; - m_host.TaskInventory[invItemID].PermsMask=0; + item.PermsGranter = UUID.Zero; + item.PermsMask = 0; m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( "run_time_permissions", new Object[] { @@ -2954,7 +3016,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return; } - if ( m_host.TaskInventory[invItemID].PermsGranter != agentID || (perm & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) + if (item.PermsGranter != agentID || (perm & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) llReleaseControls(); m_host.AddScriptLPS(1); @@ -2969,8 +3031,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms { - m_host.TaskInventory[invItemID].PermsGranter=agentID; - m_host.TaskInventory[invItemID].PermsMask=perm; + lock (m_host.TaskInventory) + { + m_host.TaskInventory[invItemID].PermsGranter = agentID; + m_host.TaskInventory[invItemID].PermsMask = perm; + } m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( "run_time_permissions", new Object[] { @@ -2990,8 +3055,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms { - m_host.TaskInventory[invItemID].PermsGranter=agentID; - m_host.TaskInventory[invItemID].PermsMask=perm; + lock (m_host.TaskInventory) + { + m_host.TaskInventory[invItemID].PermsGranter = agentID; + m_host.TaskInventory[invItemID].PermsMask = perm; + } m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( "run_time_permissions", new Object[] { @@ -3006,19 +3074,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (presence != null) { - string ownerName=resolveName(m_host.ParentGroup.RootPart.OwnerID); + string ownerName = resolveName(m_host.ParentGroup.RootPart.OwnerID); if (ownerName == String.Empty) - ownerName="(hippos)"; + ownerName = "(hippos)"; if (!m_waitingForScriptAnswer) { - m_host.TaskInventory[invItemID].PermsGranter=agentID; - m_host.TaskInventory[invItemID].PermsMask=0; - presence.ControllingClient.OnScriptAnswer+=handleScriptAnswer; + lock (m_host.TaskInventory) + { + m_host.TaskInventory[invItemID].PermsGranter = agentID; + m_host.TaskInventory[invItemID].PermsMask = 0; + } + + presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; m_waitingForScriptAnswer=true; } - presence.ControllingClient.SendScriptQuestion(m_host.UUID, m_host.ParentGroup.RootPart.Name, ownerName, invItemID, perm); + presence.ControllingClient.SendScriptQuestion( + m_host.UUID, m_host.ParentGroup.RootPart.Name, ownerName, invItemID, perm); + return; } @@ -3034,7 +3108,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (taskID != m_host.UUID) return; - UUID invItemID=InventorySelf(); + UUID invItemID = InventorySelf(); if (invItemID == UUID.Zero) return; @@ -3044,8 +3118,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) llReleaseControls(); + + lock (m_host.TaskInventory) + { + m_host.TaskInventory[invItemID].PermsMask = answer; + } - m_host.TaskInventory[invItemID].PermsMask=answer; m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( "run_time_permissions", new Object[] { new LSL_Integer(answer) }, @@ -3056,11 +3134,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + lock (m_host.TaskInventory) { - if (item.Type == 10 && item.ItemID == m_itemID) + foreach (TaskInventoryItem item in m_host.TaskInventory.Values) { - return item.PermsGranter.ToString(); + if (item.Type == 10 && item.ItemID == m_itemID) + { + return item.PermsGranter.ToString(); + } } } @@ -3071,14 +3152,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + lock (m_host.TaskInventory) { - if (item.Type == 10 && item.ItemID == m_itemID) + foreach (TaskInventoryItem item in m_host.TaskInventory.Values) { - int perms = item.PermsMask; - if (m_automaticLinkPermission) - perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS; - return perms; + if (item.Type == 10 && item.ItemID == m_itemID) + { + int perms = item.PermsMask; + if (m_automaticLinkPermission) + perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS; + return perms; + } } } @@ -3111,7 +3195,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); UUID invItemID = InventorySelf(); - if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 + + TaskInventoryItem item; + lock (m_host.TaskInventory) + { + item = m_host.TaskInventory[invItemID]; + } + + if ((item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 && !m_automaticLinkPermission) { ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!"); @@ -3119,7 +3210,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } IClientAPI client = null; - ScenePresence sp = World.GetScenePresence(m_host.TaskInventory[invItemID].PermsGranter); + ScenePresence sp = World.GetScenePresence(item.PermsGranter); if (sp != null) client = sp.ControllingClient; @@ -3162,18 +3253,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); UUID invItemID = InventorySelf(); - if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 - && !m_automaticLinkPermission) + + lock (m_host.TaskInventory) { - ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!"); - return; + if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 + && !m_automaticLinkPermission) + { + ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!"); + return; + } } + if (linknum < ScriptBaseClass.LINK_THIS) - return; + return; + SceneObjectGroup parentPrim = m_host.ParentGroup; + if (parentPrim.RootPart.AttachmentPoint != 0) return; // Fail silently if attached SceneObjectPart childPrim = null; + switch (linknum) { case ScriptBaseClass.LINK_ROOT: @@ -3236,8 +3335,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api SceneObjectGroup parentPrim = m_host.ParentGroup; 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) { parentPrim.DelinkFromGroup(part.LocalId, true); @@ -3330,13 +3431,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); int count = 0; - foreach (KeyValuePair inv in m_host.TaskInventory) + + lock (m_host.TaskInventory) { - if (inv.Value.Type == type || type == -1) + foreach (KeyValuePair inv in m_host.TaskInventory) { - count = count + 1; + if (inv.Value.Type == type || type == -1) + { + count = count + 1; + } } } + return count; } @@ -3344,13 +3450,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); ArrayList keys = new ArrayList(); - foreach (KeyValuePair inv in m_host.TaskInventory) + + lock (m_host.TaskInventory) { - if (inv.Value.Type == type || type == -1) + foreach (KeyValuePair inv in m_host.TaskInventory) { - keys.Add(inv.Value.Name); + if (inv.Value.Type == type || type == -1) + { + keys.Add(inv.Value.Name); + } } } + if (keys.Count == 0) { return String.Empty; @@ -3386,15 +3497,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } // move the first object found with this inventory name - foreach (KeyValuePair inv in m_host.TaskInventory) + lock (m_host.TaskInventory) { - if (inv.Value.Name == inventory) + foreach (KeyValuePair inv in m_host.TaskInventory) { - found = true; - objId = inv.Key; - assetType = inv.Value.Type; - objName = inv.Value.Name; - break; + if (inv.Value.Name == inventory) + { + found = true; + objId = inv.Key; + assetType = inv.Value.Type; + objName = inv.Value.Name; + break; + } } } @@ -3443,12 +3557,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llRemoveInventory(string name) { m_host.AddScriptLPS(1); - foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + + lock (m_host.TaskInventory) { - if (item.Name == name) + foreach (TaskInventoryItem item in m_host.TaskInventory.Values) { - m_host.Inventory.RemoveInventoryItem(item.ItemID); - return; + if (item.Name == name) + { + m_host.Inventory.RemoveInventoryItem(item.ItemID); + return; + } } } } @@ -3536,7 +3654,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + TaskInventoryDictionary itemDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); + + foreach (TaskInventoryItem item in itemDictionary.Values) { if (item.Type == 3 && item.Name == name) { @@ -3623,12 +3743,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api UUID soundId = UUID.Zero; if (!UUID.TryParse(impact_sound, out soundId)) { - foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + lock (m_host.TaskInventory) { - if (item.Type == (int)AssetType.Sound && item.Name == impact_sound) + foreach (TaskInventoryItem item in m_host.TaskInventory.Values) { - soundId = item.AssetID; - break; + if (item.Type == (int)AssetType.Sound && item.Name == impact_sound) + { + soundId = item.AssetID; + break; + } } } } @@ -3675,7 +3798,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api UUID partItemID; foreach (SceneObjectPart part in parts) { - foreach (TaskInventoryItem item in part.TaskInventory.Values) + TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); + + foreach (TaskInventoryItem item in itemsDictionary.Values) { if (item.Type == ScriptBaseClass.INVENTORY_SCRIPT) { @@ -3684,7 +3809,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (m_host.ParentGroup.Children.Count == 1) linkNumber = 0; - object[] resobj = new object[] { new LSL_Integer(linkNumber), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id) @@ -3875,22 +3999,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_String llGetScriptName() { - string result = String.Empty; m_host.AddScriptLPS(1); - foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + lock (m_host.TaskInventory) { - if (item.Type == 10 && item.ItemID == m_itemID) + foreach (TaskInventoryItem item in m_host.TaskInventory.Values) { - result = item.Name!=null?item.Name:String.Empty; - break; + if (item.Type == 10 && item.ItemID == m_itemID) + { + result = item.Name!=null?item.Name:String.Empty; + break; + } } } return result; - } // this function to understand which shape it is (taken from meshmerizer) @@ -4142,20 +4267,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_String llGetInventoryKey(string name) { m_host.AddScriptLPS(1); - foreach (KeyValuePair inv in m_host.TaskInventory) + + lock (m_host.TaskInventory) { - if (inv.Value.Name == name) + foreach (KeyValuePair inv in m_host.TaskInventory) { - if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) - { - return inv.Value.AssetID.ToString(); - } - else + if (inv.Value.Name == name) { - return UUID.Zero.ToString(); + if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) + { + return inv.Value.AssetID.ToString(); + } + else + { + return UUID.Zero.ToString(); + } } - } } + } + return UUID.Zero.ToString(); } @@ -5540,11 +5670,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api private UUID GetTaskInventoryItem(string name) { - foreach (KeyValuePair inv in m_host.TaskInventory) + lock (m_host.TaskInventory) { - if (inv.Value.Name == name) - return inv.Key; + foreach (KeyValuePair inv in m_host.TaskInventory) + { + if (inv.Value.Name == name) + return inv.Key; + } } + return UUID.Zero; } @@ -5853,16 +5987,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } // copy the first script found with this inventory name - foreach (KeyValuePair inv in m_host.TaskInventory) + lock (m_host.TaskInventory) { - if (inv.Value.Name == name) + foreach (KeyValuePair inv in m_host.TaskInventory) { - // make sure the object is a script - if (10 == inv.Value.Type) + if (inv.Value.Name == name) { - found = true; - srcId = inv.Key; - break; + // make sure the object is a script + if (10 == inv.Value.Type) + { + found = true; + srcId = inv.Key; + break; + } } } } @@ -7614,25 +7751,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Integer llGetInventoryPermMask(string item, int mask) { m_host.AddScriptLPS(1); - foreach (KeyValuePair inv in m_host.TaskInventory) + + lock (m_host.TaskInventory) { - if (inv.Value.Name == item) + foreach (KeyValuePair inv in m_host.TaskInventory) { - switch (mask) + if (inv.Value.Name == item) { - case 0: - return (int)inv.Value.BasePermissions; - case 1: - return (int)inv.Value.CurrentPermissions; - case 2: - return (int)inv.Value.GroupPermissions; - case 3: - return (int)inv.Value.EveryonePermissions; - case 4: - return (int)inv.Value.NextPermissions; + switch (mask) + { + case 0: + return (int)inv.Value.BasePermissions; + case 1: + return (int)inv.Value.CurrentPermissions; + case 2: + return (int)inv.Value.GroupPermissions; + case 3: + return (int)inv.Value.EveryonePermissions; + case 4: + return (int)inv.Value.NextPermissions; + } } } } + return -1; } @@ -7645,14 +7787,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_String llGetInventoryCreator(string item) { m_host.AddScriptLPS(1); - foreach (KeyValuePair inv in m_host.TaskInventory) + + lock (m_host.TaskInventory) { - if (inv.Value.Name == item) + foreach (KeyValuePair inv in m_host.TaskInventory) { - return inv.Value.CreatorID.ToString(); + if (inv.Value.Name == item) + { + return inv.Value.CreatorID.ToString(); + } } } + llSay(0, "No item name '" + item + "'"); + return String.Empty; } @@ -8143,13 +8291,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Integer llGetInventoryType(string name) { m_host.AddScriptLPS(1); - foreach (KeyValuePair inv in m_host.TaskInventory) + + lock (m_host.TaskInventory) { - if (inv.Value.Name == name) + foreach (KeyValuePair inv in m_host.TaskInventory) { - return inv.Value.Type; + if (inv.Value.Name == name) + { + return inv.Value.Type; + } } } + return -1; } @@ -8174,16 +8327,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Vector llGetCameraPos() { m_host.AddScriptLPS(1); - UUID invItemID=InventorySelf(); + UUID invItemID = InventorySelf(); + if (invItemID == UUID.Zero) return new LSL_Vector(); - if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) - return new LSL_Vector(); - if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) + + lock (m_host.TaskInventory) { - ShoutError("No permissions to track the camera"); - return new LSL_Vector(); + if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) + return new LSL_Vector(); + + if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) + { + ShoutError("No permissions to track the camera"); + return new LSL_Vector(); + } } + ScenePresence presence = World.GetScenePresence(m_host.OwnerID); if (presence != null) { @@ -8196,21 +8356,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Rotation llGetCameraRot() { m_host.AddScriptLPS(1); - UUID invItemID=InventorySelf(); + UUID invItemID = InventorySelf(); if (invItemID == UUID.Zero) return new LSL_Rotation(); - if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) - return new LSL_Rotation(); - if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) + + lock (m_host.TaskInventory) { - ShoutError("No permissions to track the camera"); - return new LSL_Rotation(); + if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) + return new LSL_Rotation(); + + if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) + { + ShoutError("No permissions to track the camera"); + return new LSL_Rotation(); + } } + ScenePresence presence = World.GetScenePresence(m_host.OwnerID); if (presence != null) { return new LSL_Rotation(presence.CameraRotation.X, presence.CameraRotation.Y, presence.CameraRotation.Z, presence.CameraRotation.W); } + return new LSL_Rotation(); } @@ -8345,17 +8512,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); // our key in the object we are in - UUID invItemID=InventorySelf(); + UUID invItemID = InventorySelf(); if (invItemID == UUID.Zero) return; // the object we are in UUID objectID = m_host.ParentUUID; if (objectID == UUID.Zero) return; - // we need the permission first, to know which avatar we want to set the camera for - UUID agentID = m_host.TaskInventory[invItemID].PermsGranter; - if (agentID == UUID.Zero) return; - if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return; + UUID agentID; + lock (m_host.TaskInventory) + { + // we need the permission first, to know which avatar we want to set the camera for + agentID = m_host.TaskInventory[invItemID].PermsGranter; + + if (agentID == UUID.Zero) return; + if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return; + } ScenePresence presence = World.GetScenePresence(agentID); @@ -8404,9 +8576,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (objectID == UUID.Zero) return; // we need the permission first, to know which avatar we want to clear the camera for - UUID agentID = m_host.TaskInventory[invItemID].PermsGranter; - if (agentID == UUID.Zero) return; - if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return; + UUID agentID; + lock (m_host.TaskInventory) + { + agentID = m_host.TaskInventory[invItemID].PermsGranter; + if (agentID == UUID.Zero) return; + if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return; + } ScenePresence presence = World.GetScenePresence(agentID); @@ -8816,14 +8992,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return new LSL_List(); } - internal UUID ScriptByName(string name) { - foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + lock (m_host.TaskInventory) { - if (item.Type == 10 && item.Name == name) - return item.ItemID; + foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + { + if (item.Type == 10 && item.Name == name) + return item.ItemID; + } } + return UUID.Zero; } @@ -8858,7 +9037,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); + + foreach (TaskInventoryItem item in itemsDictionary.Values) { if (item.Type == 7 && item.Name == name) { @@ -8900,7 +9081,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - foreach (TaskInventoryItem item in m_host.TaskInventory.Values) + TaskInventoryDictionary itemsDictionary = (TaskInventoryDictionary)m_host.TaskInventory.Clone(); + + foreach (TaskInventoryItem item in itemsDictionary.Values) { if (item.Type == 7 && item.Name == name) { diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index 96c1698..20e70d0 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -231,9 +231,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance m_stateSource = stateSource; m_postOnRez = postOnRez; - if (part != null && part.TaskInventory.ContainsKey(m_ItemID)) + if (part != null) { - m_thisScriptTask = part.TaskInventory[m_ItemID]; + lock (part.TaskInventory) + { + if (part.TaskInventory.ContainsKey(m_ItemID)) + { + m_thisScriptTask = part.TaskInventory[m_ItemID]; + } + } } ApiManager am = new ApiManager(); @@ -399,15 +405,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance private void ReleaseControls() { - SceneObjectPart part=m_Engine.World.GetSceneObjectPart(m_LocalID); - if (part != null && part.TaskInventory.ContainsKey(m_ItemID)) + SceneObjectPart part = m_Engine.World.GetSceneObjectPart(m_LocalID); + + if (part != null) { - UUID permsGranter = part.TaskInventory[m_ItemID].PermsGranter; - int permsMask = part.TaskInventory[m_ItemID].PermsMask; + int permsMask; + UUID permsGranter; + lock (part.TaskInventory) + { + if (!part.TaskInventory.ContainsKey(m_ItemID)) + return; + + permsGranter = part.TaskInventory[m_ItemID].PermsGranter; + permsMask = part.TaskInventory[m_ItemID].PermsMask; + } if ((permsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0) { - ScenePresence presence = m_Engine.World.GetScenePresence(permsGranter); if (presence != null) presence.UnRegisterControlEventsToScript(m_LocalID, m_ItemID); -- cgit v1.1