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