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.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
/// <param name="silent">If true then deletion is not broadcast to clients</param>
public void DeleteGroup(bool silent)
{
lock (m_parts)
{
foreach (SceneObjectPart part in m_parts.Values)
{
// part.Inventory.RemoveScriptInstances();
Scene.ForEachScenePresence(delegate(ScenePresence avatar)
{
if (avatar.ParentID == LocalId)
{
avatar.StandUp();
}
List<SceneObjectPart> parts;
if (!silent)
{
part.UpdateFlag = 0;
if (part == m_rootPart)
avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
}
});
}
lock (m_parts)
parts = m_parts.Values.ToList();
foreach (SceneObjectPart part in parts)
{
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);
}
});
}
}