From 16f296f48932379a89c52f095eae199347f33407 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 15 Sep 2010 21:41:42 +0100 Subject: Instead of locking SOG.Children when a group is being removed from the scene, iterate over an unlocked list instead Previously, deadlock was possible because deleting a group took a SOG.Children lock then an m_entityUpdates.SyncRoot lock in LLClientView At the same time, a thread starting from LLClientView.ProcessEntityUpdates() could take an m_entityUpdates.SyncRoot lock then later attempt to take a SOG.Children lock in PermissionsModule.GenerateClientFlags() and later on Taking a children list in SOG appears to be a better solution than changing PermissionsModule to not relook up the prim. Going the permission modules root would require that all downstream modules not take a SOG.Children lock either --- .../Region/Framework/Scenes/SceneObjectGroup.cs | 32 ++++++++++++---------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index dc6509d..99c2abf 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -29,6 +29,7 @@ using System; using System.Collections.Generic; using System.Drawing; using System.IO; +using System.Linq; using System.Threading; using System.Xml; using System.Xml.Serialization; @@ -1236,26 +1237,27 @@ namespace OpenSim.Region.Framework.Scenes /// If true then deletion is not broadcast to clients public void DeleteGroup(bool silent) { + List parts; + lock (m_parts) + parts = m_parts.Values.ToList(); + + foreach (SceneObjectPart part in parts) { - foreach (SceneObjectPart part in m_parts.Values) + Scene.ForEachScenePresence(delegate(ScenePresence avatar) { -// part.Inventory.RemoveScriptInstances(); - Scene.ForEachScenePresence(delegate(ScenePresence avatar) + if (avatar.ParentID == LocalId) { - if (avatar.ParentID == LocalId) - { - avatar.StandUp(); - } + avatar.StandUp(); + } - if (!silent) - { - part.UpdateFlag = 0; - if (part == m_rootPart) - avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); - } - }); - } + if (!silent) + { + part.UpdateFlag = 0; + if (part == m_rootPart) + avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); + } + }); } } -- cgit v1.1