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
viewer-2-initial-appearance
Justin Clark-Casey (justincc) 2010-09-15 21:41:42 +01:00
parent 8ed08a10d9
commit 16f296f489
1 changed files with 21 additions and 19 deletions

View File

@ -29,6 +29,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.IO; using System.IO;
using System.Linq;
using System.Threading; using System.Threading;
using System.Xml; using System.Xml;
using System.Xml.Serialization; using System.Xml.Serialization;
@ -1236,26 +1237,27 @@ namespace OpenSim.Region.Framework.Scenes
/// <param name="silent">If true then deletion is not broadcast to clients</param> /// <param name="silent">If true then deletion is not broadcast to clients</param>
public void DeleteGroup(bool silent) public void DeleteGroup(bool silent)
{ {
lock (m_parts) List<SceneObjectPart> parts;
{
foreach (SceneObjectPart part in m_parts.Values)
{
// part.Inventory.RemoveScriptInstances();
Scene.ForEachScenePresence(delegate(ScenePresence avatar)
{
if (avatar.ParentID == LocalId)
{
avatar.StandUp();
}
if (!silent) lock (m_parts)
{ parts = m_parts.Values.ToList();
part.UpdateFlag = 0;
if (part == m_rootPart) foreach (SceneObjectPart part in parts)
avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); {
} Scene.ForEachScenePresence(delegate(ScenePresence avatar)
}); {
} if (avatar.ParentID == LocalId)
{
avatar.StandUp();
}
if (!silent)
{
part.UpdateFlag = 0;
if (part == m_rootPart)
avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
}
});
} }
} }