aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2010-08-26 00:08:53 +0100
committerJustin Clark-Casey (justincc)2010-08-26 00:08:53 +0100
commit8031f8ec09df4f654c86a9c7bc498664f7b9d9dc (patch)
treed6a6da4d448b9bc11ff8d1078b9be089b9872151 /OpenSim/Region/Framework/Scenes
parentminor: remove mono compiler warning (diff)
downloadopensim-SC-8031f8ec09df4f654c86a9c7bc498664f7b9d9dc.zip
opensim-SC-8031f8ec09df4f654c86a9c7bc498664f7b9d9dc.tar.gz
opensim-SC-8031f8ec09df4f654c86a9c7bc498664f7b9d9dc.tar.bz2
opensim-SC-8031f8ec09df4f654c86a9c7bc498664f7b9d9dc.tar.xz
Improve consistency of locking for SOG.m_parts in order to avoid race conditions in linking and unlinking
Diffstat (limited to 'OpenSim/Region/Framework/Scenes')
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs21
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs38
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs35
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs111
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs131
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs5
6 files changed, 205 insertions, 136 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 9fef8f4..379128a 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -1974,7 +1974,7 @@ namespace OpenSim.Region.Framework.Scenes
1974 if (null == group) 1974 if (null == group)
1975 return null; 1975 return null;
1976 1976
1977 if (!Permissions.CanRezObject(group.Children.Count, item.OwnerID, pos)) 1977 if (!Permissions.CanRezObject(group.PrimCount, item.OwnerID, pos))
1978 return null; 1978 return null;
1979 1979
1980 if (!Permissions.BypassPermissions()) 1980 if (!Permissions.BypassPermissions())
@@ -2051,8 +2051,11 @@ namespace OpenSim.Region.Framework.Scenes
2051 sog.SetGroup(groupID, remoteClient); 2051 sog.SetGroup(groupID, remoteClient);
2052 sog.ScheduleGroupForFullUpdate(); 2052 sog.ScheduleGroupForFullUpdate();
2053 2053
2054 foreach (SceneObjectPart child in sog.Children.Values) 2054 lock (sog.Children)
2055 child.Inventory.ChangeInventoryOwner(ownerID); 2055 {
2056 foreach (SceneObjectPart child in sog.Children.Values)
2057 child.Inventory.ChangeInventoryOwner(ownerID);
2058 }
2056 } 2059 }
2057 else 2060 else
2058 { 2061 {
@@ -2062,16 +2065,18 @@ namespace OpenSim.Region.Framework.Scenes
2062 if (sog.GroupID != groupID) 2065 if (sog.GroupID != groupID)
2063 continue; 2066 continue;
2064 2067
2065 foreach (SceneObjectPart child in sog.Children.Values) 2068 lock (sog.Children)
2066 { 2069 {
2067 child.LastOwnerID = child.OwnerID; 2070 foreach (SceneObjectPart child in sog.Children.Values)
2068 child.Inventory.ChangeInventoryOwner(groupID); 2071 {
2072 child.LastOwnerID = child.OwnerID;
2073 child.Inventory.ChangeInventoryOwner(groupID);
2074 }
2069 } 2075 }
2070 2076
2071 sog.SetOwnerId(groupID); 2077 sog.SetOwnerId(groupID);
2072 sog.ApplyNextOwnerPermissions(); 2078 sog.ApplyNextOwnerPermissions();
2073 } 2079 }
2074
2075 } 2080 }
2076 2081
2077 foreach (uint localID in localIDs) 2082 foreach (uint localID in localIDs)
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index e25b1f1..9f1575d 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -156,21 +156,29 @@ namespace OpenSim.Region.Framework.Scenes
156 } 156 }
157 break; 157 break;
158 } 158 }
159 else 159 else
160 { 160 {
161 // We also need to check the children of this prim as they 161 // We also need to check the children of this prim as they
162 // can be selected as well and send property information 162 // can be selected as well and send property information
163 bool foundPrim = false; 163 bool foundPrim = false;
164 foreach (KeyValuePair<UUID, SceneObjectPart> child in ((SceneObjectGroup) ent).Children) 164
165 { 165 SceneObjectGroup sog = ent as SceneObjectGroup;
166 if (child.Value.LocalId == primLocalID) 166
167 { 167 lock (sog.Children)
168 child.Value.GetProperties(remoteClient); 168 {
169 foundPrim = true; 169 foreach (KeyValuePair<UUID, SceneObjectPart> child in (sog.Children))
170 break; 170 {
171 } 171 if (child.Value.LocalId == primLocalID)
172 } 172 {
173 if (foundPrim) break; 173 child.Value.GetProperties(remoteClient);
174 foundPrim = true;
175 break;
176 }
177 }
178 }
179
180 if (foundPrim)
181 break;
174 } 182 }
175 } 183 }
176 } 184 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index b808c6d..8556105 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -1756,8 +1756,9 @@ namespace OpenSim.Region.Framework.Scenes
1756 1756
1757 if (group.RootPart == null) 1757 if (group.RootPart == null)
1758 { 1758 {
1759 m_log.ErrorFormat("[SCENE]: Found a SceneObjectGroup with m_rootPart == null and {0} children", 1759 m_log.ErrorFormat(
1760 group.Children == null ? 0 : group.Children.Count); 1760 "[SCENE]: Found a SceneObjectGroup with m_rootPart == null and {0} children",
1761 group.Children == null ? 0 : group.PrimCount);
1761 } 1762 }
1762 1763
1763 AddRestoredSceneObject(group, true, true); 1764 AddRestoredSceneObject(group, true, true);
@@ -2064,18 +2065,22 @@ namespace OpenSim.Region.Framework.Scenes
2064 group.RemoveScriptInstances(true); 2065 group.RemoveScriptInstances(true);
2065 } 2066 }
2066 2067
2067 foreach (SceneObjectPart part in group.Children.Values) 2068 lock (group.Children)
2068 { 2069 {
2069 if (part.IsJoint() && ((part.Flags & PrimFlags.Physics) != 0)) 2070 foreach (SceneObjectPart part in group.Children.Values)
2070 { 2071 {
2071 PhysicsScene.RequestJointDeletion(part.Name); // FIXME: what if the name changed? 2072 if (part.IsJoint() && ((part.Flags & PrimFlags.Physics) != 0))
2072 } 2073 {
2073 else if (part.PhysActor != null) 2074 PhysicsScene.RequestJointDeletion(part.Name); // FIXME: what if the name changed?
2074 { 2075 }
2075 PhysicsScene.RemovePrim(part.PhysActor); 2076 else if (part.PhysActor != null)
2076 part.PhysActor = null; 2077 {
2078 PhysicsScene.RemovePrim(part.PhysActor);
2079 part.PhysActor = null;
2080 }
2077 } 2081 }
2078 } 2082 }
2083
2079// if (rootPart.PhysActor != null) 2084// if (rootPart.PhysActor != null)
2080// { 2085// {
2081// PhysicsScene.RemovePrim(rootPart.PhysActor); 2086// PhysicsScene.RemovePrim(rootPart.PhysActor);
@@ -2426,14 +2431,16 @@ namespace OpenSim.Region.Framework.Scenes
2426 2431
2427 // Force allocation of new LocalId 2432 // Force allocation of new LocalId
2428 // 2433 //
2429 foreach (SceneObjectPart p in sceneObject.Children.Values) 2434 lock (sceneObject.Children)
2430 p.LocalId = 0; 2435 {
2436 foreach (SceneObjectPart p in sceneObject.Children.Values)
2437 p.LocalId = 0;
2438 }
2431 2439
2432 if (sceneObject.IsAttachmentCheckFull()) // Attachment 2440 if (sceneObject.IsAttachmentCheckFull()) // Attachment
2433 { 2441 {
2434 sceneObject.RootPart.AddFlag(PrimFlags.TemporaryOnRez); 2442 sceneObject.RootPart.AddFlag(PrimFlags.TemporaryOnRez);
2435 sceneObject.RootPart.AddFlag(PrimFlags.Phantom); 2443 sceneObject.RootPart.AddFlag(PrimFlags.Phantom);
2436
2437 2444
2438 // Don't sent a full update here because this will cause full updates to be sent twice for 2445 // Don't sent a full update here because this will cause full updates to be sent twice for
2439 // attachments on region crossings, resulting in viewer glitches. 2446 // attachments on region crossings, resulting in viewer glitches.
@@ -2447,7 +2454,6 @@ namespace OpenSim.Region.Framework.Scenes
2447 2454
2448 if (sp != null) 2455 if (sp != null)
2449 { 2456 {
2450
2451 SceneObjectGroup grp = sceneObject; 2457 SceneObjectGroup grp = sceneObject;
2452 2458
2453 m_log.DebugFormat( 2459 m_log.DebugFormat(
@@ -2459,7 +2465,6 @@ namespace OpenSim.Region.Framework.Scenes
2459 2465
2460 if (AttachmentsModule != null) 2466 if (AttachmentsModule != null)
2461 AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false); 2467 AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false);
2462
2463 } 2468 }
2464 else 2469 else
2465 { 2470 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 31faeec..2b24706 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -364,45 +364,48 @@ namespace OpenSim.Region.Framework.Scenes
364// "[SCENE GRAPH]: Adding object {0} {1} to region {2}", 364// "[SCENE GRAPH]: Adding object {0} {1} to region {2}",
365// sceneObject.Name, sceneObject.UUID, m_parentScene.RegionInfo.RegionName); 365// sceneObject.Name, sceneObject.UUID, m_parentScene.RegionInfo.RegionName);
366 366
367 if (m_parentScene.m_clampPrimSize) 367 lock (sceneObject.Children)
368 { 368 {
369 foreach (SceneObjectPart part in sceneObject.Children.Values) 369 if (m_parentScene.m_clampPrimSize)
370 { 370 {
371 Vector3 scale = part.Shape.Scale; 371 foreach (SceneObjectPart part in sceneObject.Children.Values)
372 372 {
373 if (scale.X > m_parentScene.m_maxNonphys) 373 Vector3 scale = part.Shape.Scale;
374 scale.X = m_parentScene.m_maxNonphys; 374
375 if (scale.Y > m_parentScene.m_maxNonphys) 375 if (scale.X > m_parentScene.m_maxNonphys)
376 scale.Y = m_parentScene.m_maxNonphys; 376 scale.X = m_parentScene.m_maxNonphys;
377 if (scale.Z > m_parentScene.m_maxNonphys) 377 if (scale.Y > m_parentScene.m_maxNonphys)
378 scale.Z = m_parentScene.m_maxNonphys; 378 scale.Y = m_parentScene.m_maxNonphys;
379 379 if (scale.Z > m_parentScene.m_maxNonphys)
380 part.Shape.Scale = scale; 380 scale.Z = m_parentScene.m_maxNonphys;
381
382 part.Shape.Scale = scale;
383 }
381 } 384 }
382 } 385
386 sceneObject.AttachToScene(m_parentScene);
387
388 if (sendClientUpdates)
389 sceneObject.ScheduleGroupForFullUpdate();
390
391 Entities.Add(sceneObject);
392 m_numPrim += sceneObject.Children.Count;
383 393
384 sceneObject.AttachToScene(m_parentScene); 394 if (attachToBackup)
395 sceneObject.AttachToBackup();
385 396
386 if (sendClientUpdates) 397 if (OnObjectCreate != null)
387 sceneObject.ScheduleGroupForFullUpdate(); 398 OnObjectCreate(sceneObject);
388 399
389 Entities.Add(sceneObject); 400 lock (m_dictionary_lock)
390 m_numPrim += sceneObject.Children.Count;
391
392 if (attachToBackup)
393 sceneObject.AttachToBackup();
394
395 if (OnObjectCreate != null)
396 OnObjectCreate(sceneObject);
397
398 lock (m_dictionary_lock)
399 {
400 SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject;
401 SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject;
402 foreach (SceneObjectPart part in sceneObject.Children.Values)
403 { 401 {
404 SceneObjectGroupsByFullID[part.UUID] = sceneObject; 402 SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject;
405 SceneObjectGroupsByLocalID[part.LocalId] = sceneObject; 403 SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject;
404 foreach (SceneObjectPart part in sceneObject.Children.Values)
405 {
406 SceneObjectGroupsByFullID[part.UUID] = sceneObject;
407 SceneObjectGroupsByLocalID[part.LocalId] = sceneObject;
408 }
406 } 409 }
407 } 410 }
408 } 411 }
@@ -420,11 +423,16 @@ namespace OpenSim.Region.Framework.Scenes
420 { 423 {
421 if (!resultOfObjectLinked) 424 if (!resultOfObjectLinked)
422 { 425 {
423 m_numPrim -= ((SceneObjectGroup) Entities[uuid]).Children.Count; 426 SceneObjectGroup sog = Entities[uuid] as SceneObjectGroup;
424 427
425 if ((((SceneObjectGroup)Entities[uuid]).RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) 428 lock (sog.Children)
426 { 429 {
427 RemovePhysicalPrim(((SceneObjectGroup)Entities[uuid]).Children.Count); 430 m_numPrim -= sog.PrimCount;
431
432 if ((((SceneObjectGroup)Entities[uuid]).RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics)
433 {
434 RemovePhysicalPrim(sog.PrimCount);
435 }
428 } 436 }
429 } 437 }
430 438
@@ -1603,7 +1611,7 @@ namespace OpenSim.Region.Framework.Scenes
1603 { 1611 {
1604 if (part != null) 1612 if (part != null)
1605 { 1613 {
1606 if (part.ParentGroup.Children.Count != 1) // Skip single 1614 if (part.ParentGroup.PrimCount != 1) // Skip single
1607 { 1615 {
1608 if (part.LinkNum < 2) // Root 1616 if (part.LinkNum < 2) // Root
1609 rootParts.Add(part); 1617 rootParts.Add(part);
@@ -1631,8 +1639,15 @@ namespace OpenSim.Region.Framework.Scenes
1631 // However, editing linked parts and unlinking may be different 1639 // However, editing linked parts and unlinking may be different
1632 // 1640 //
1633 SceneObjectGroup group = root.ParentGroup; 1641 SceneObjectGroup group = root.ParentGroup;
1634 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Children.Values); 1642
1635 int numChildren = group.Children.Count; 1643 List<SceneObjectPart> newSet = null;
1644 int numChildren = -1;
1645
1646 lock (group.Children)
1647 {
1648 newSet = new List<SceneObjectPart>(group.Children.Values);
1649 numChildren = group.PrimCount;
1650 }
1636 1651
1637 // If there are prims left in a link set, but the root is 1652 // If there are prims left in a link set, but the root is
1638 // slated for unlink, we need to do this 1653 // slated for unlink, we need to do this
@@ -1711,12 +1726,17 @@ namespace OpenSim.Region.Framework.Scenes
1711 { 1726 {
1712 if (ent is SceneObjectGroup) 1727 if (ent is SceneObjectGroup)
1713 { 1728 {
1714 foreach (KeyValuePair<UUID, SceneObjectPart> subent in ((SceneObjectGroup)ent).Children) 1729 SceneObjectGroup sog = ent as SceneObjectGroup;
1730
1731 lock (sog.Children)
1715 { 1732 {
1716 if (subent.Value.LocalId == localID) 1733 foreach (KeyValuePair<UUID, SceneObjectPart> subent in sog.Children)
1717 { 1734 {
1718 objid = subent.Key; 1735 if (subent.Value.LocalId == localID)
1719 obj = subent.Value; 1736 {
1737 objid = subent.Key;
1738 obj = subent.Value;
1739 }
1720 } 1740 }
1721 } 1741 }
1722 } 1742 }
@@ -1781,7 +1801,8 @@ namespace OpenSim.Region.Framework.Scenes
1781 SceneObjectGroup original = GetGroupByPrim(originalPrimID); 1801 SceneObjectGroup original = GetGroupByPrim(originalPrimID);
1782 if (original != null) 1802 if (original != null)
1783 { 1803 {
1784 if (m_parentScene.Permissions.CanDuplicateObject(original.Children.Count, original.UUID, AgentID, original.AbsolutePosition)) 1804 if (m_parentScene.Permissions.CanDuplicateObject(
1805 original.PrimCount, original.UUID, AgentID, original.AbsolutePosition))
1785 { 1806 {
1786 SceneObjectGroup copy = original.Copy(true); 1807 SceneObjectGroup copy = original.Copy(true);
1787 copy.AbsolutePosition = copy.AbsolutePosition + offset; 1808 copy.AbsolutePosition = copy.AbsolutePosition + offset;
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 952d280..5ee8d73 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -213,7 +213,7 @@ namespace OpenSim.Region.Framework.Scenes
213 /// </summary> 213 /// </summary>
214 public int PrimCount 214 public int PrimCount
215 { 215 {
216 get { return m_parts.Count; } 216 get { lock (m_parts) { return m_parts.Count; } }
217 } 217 }
218 218
219 protected Quaternion m_rotation = Quaternion.Identity; 219 protected Quaternion m_rotation = Quaternion.Identity;
@@ -237,6 +237,7 @@ namespace OpenSim.Region.Framework.Scenes
237 237
238 /// <value> 238 /// <value>
239 /// The parts of this scene object group. You must lock this property before using it. 239 /// The parts of this scene object group. You must lock this property before using it.
240 /// If you want to know the number of children, consider using the PrimCount property instead
240 /// </value> 241 /// </value>
241 public Dictionary<UUID, SceneObjectPart> Children 242 public Dictionary<UUID, SceneObjectPart> Children
242 { 243 {
@@ -298,6 +299,7 @@ namespace OpenSim.Region.Framework.Scenes
298 { 299 {
299 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 300 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
300 } 301 }
302
301 if (RootPart.GetStatusSandbox()) 303 if (RootPart.GetStatusSandbox())
302 { 304 {
303 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 305 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -308,6 +310,7 @@ namespace OpenSim.Region.Framework.Scenes
308 return; 310 return;
309 } 311 }
310 } 312 }
313
311 lock (m_parts) 314 lock (m_parts)
312 { 315 {
313 foreach (SceneObjectPart part in m_parts.Values) 316 foreach (SceneObjectPart part in m_parts.Values)
@@ -558,21 +561,23 @@ namespace OpenSim.Region.Framework.Scenes
558 if (m_rootPart.LocalId == 0) 561 if (m_rootPart.LocalId == 0)
559 m_rootPart.LocalId = m_scene.AllocateLocalId(); 562 m_rootPart.LocalId = m_scene.AllocateLocalId();
560 563
561 // No need to lock here since the object isn't yet in a scene 564 lock (m_parts)
562 foreach (SceneObjectPart part in m_parts.Values)
563 { 565 {
564 if (Object.ReferenceEquals(part, m_rootPart)) 566 foreach (SceneObjectPart part in m_parts.Values)
565 {
566 continue;
567 }
568
569 if (part.LocalId == 0)
570 { 567 {
571 part.LocalId = m_scene.AllocateLocalId(); 568 if (Object.ReferenceEquals(part, m_rootPart))
569 {
570 continue;
571 }
572
573 if (part.LocalId == 0)
574 {
575 part.LocalId = m_scene.AllocateLocalId();
576 }
577
578 part.ParentID = m_rootPart.LocalId;
579 //m_log.DebugFormat("[SCENE]: Given local id {0} to part {1}, linknum {2}, parent {3} {4}", part.LocalId, part.UUID, part.LinkNum, part.ParentID, part.ParentUUID);
572 } 580 }
573
574 part.ParentID = m_rootPart.LocalId;
575 //m_log.DebugFormat("[SCENE]: Given local id {0} to part {1}, linknum {2}, parent {3} {4}", part.LocalId, part.UUID, part.LinkNum, part.ParentID, part.ParentUUID);
576 } 581 }
577 582
578 ApplyPhysics(m_scene.m_physicalPrim); 583 ApplyPhysics(m_scene.m_physicalPrim);
@@ -670,7 +675,7 @@ namespace OpenSim.Region.Framework.Scenes
670 minY = 256f; 675 minY = 256f;
671 minZ = 8192f; 676 minZ = 8192f;
672 677
673 lock(m_parts); 678 lock(m_parts)
674 { 679 {
675 foreach (SceneObjectPart part in m_parts.Values) 680 foreach (SceneObjectPart part in m_parts.Values)
676 { 681 {
@@ -995,9 +1000,12 @@ namespace OpenSim.Region.Framework.Scenes
995 m_rootPart.AttachedAvatar = agentID; 1000 m_rootPart.AttachedAvatar = agentID;
996 1001
997 //Anakin Lohner bug #3839 1002 //Anakin Lohner bug #3839
998 foreach (SceneObjectPart p in m_parts.Values) 1003 lock (m_parts)
999 { 1004 {
1000 p.AttachedAvatar = agentID; 1005 foreach (SceneObjectPart p in m_parts.Values)
1006 {
1007 p.AttachedAvatar = agentID;
1008 }
1001 } 1009 }
1002 1010
1003 if (m_rootPart.PhysActor != null) 1011 if (m_rootPart.PhysActor != null)
@@ -1065,10 +1073,14 @@ namespace OpenSim.Region.Framework.Scenes
1065 1073
1066 AbsolutePosition = detachedpos; 1074 AbsolutePosition = detachedpos;
1067 m_rootPart.AttachedAvatar = UUID.Zero; 1075 m_rootPart.AttachedAvatar = UUID.Zero;
1068 //Anakin Lohner bug #3839 1076
1069 foreach (SceneObjectPart p in m_parts.Values) 1077 //Anakin Lohner bug #3839
1078 lock (m_parts)
1070 { 1079 {
1071 p.AttachedAvatar = UUID.Zero; 1080 foreach (SceneObjectPart p in m_parts.Values)
1081 {
1082 p.AttachedAvatar = UUID.Zero;
1083 }
1072 } 1084 }
1073 1085
1074 m_rootPart.SetParentLocalId(0); 1086 m_rootPart.SetParentLocalId(0);
@@ -1094,10 +1106,14 @@ namespace OpenSim.Region.Framework.Scenes
1094 } 1106 }
1095 1107
1096 m_rootPart.AttachedAvatar = UUID.Zero; 1108 m_rootPart.AttachedAvatar = UUID.Zero;
1109
1097 //Anakin Lohner bug #3839 1110 //Anakin Lohner bug #3839
1098 foreach (SceneObjectPart p in m_parts.Values) 1111 lock (m_parts)
1099 { 1112 {
1100 p.AttachedAvatar = UUID.Zero; 1113 foreach (SceneObjectPart p in m_parts.Values)
1114 {
1115 p.AttachedAvatar = UUID.Zero;
1116 }
1101 } 1117 }
1102 1118
1103 m_rootPart.SetParentLocalId(0); 1119 m_rootPart.SetParentLocalId(0);
@@ -1160,9 +1176,8 @@ namespace OpenSim.Region.Framework.Scenes
1160 part.ParentID = 0; 1176 part.ParentID = 0;
1161 part.LinkNum = 0; 1177 part.LinkNum = 0;
1162 1178
1163 // No locking required since the SOG should not be in the scene yet - one can't change root parts after 1179 lock (m_parts)
1164 // the scene object has been attached to the scene 1180 m_parts.Add(m_rootPart.UUID, m_rootPart);
1165 m_parts.Add(m_rootPart.UUID, m_rootPart);
1166 } 1181 }
1167 1182
1168 /// <summary> 1183 /// <summary>
@@ -1625,7 +1640,7 @@ namespace OpenSim.Region.Framework.Scenes
1625 } 1640 }
1626 1641
1627 /// <summary> 1642 /// <summary>
1628 /// 1643 /// Copy the given part as the root part of this scene object.
1629 /// </summary> 1644 /// </summary>
1630 /// <param name="part"></param> 1645 /// <param name="part"></param>
1631 /// <param name="cAgentID"></param> 1646 /// <param name="cAgentID"></param>
@@ -1882,11 +1897,12 @@ namespace OpenSim.Region.Framework.Scenes
1882 /// <param name="cGroupID"></param> 1897 /// <param name="cGroupID"></param>
1883 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 1898 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1884 { 1899 {
1885 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 1900 SceneObjectPart newPart = null;
1886 newPart.SetParent(this); 1901
1887
1888 lock (m_parts) 1902 lock (m_parts)
1889 { 1903 {
1904 newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
1905 newPart.SetParent(this);
1890 m_parts.Add(newPart.UUID, newPart); 1906 m_parts.Add(newPart.UUID, newPart);
1891 } 1907 }
1892 1908
@@ -1903,14 +1919,15 @@ namespace OpenSim.Region.Framework.Scenes
1903 /// </summary> 1919 /// </summary>
1904 public void ResetIDs() 1920 public void ResetIDs()
1905 { 1921 {
1906 // As this is only ever called for prims which are not currently part of the scene (and hence 1922 lock (m_parts)
1907 // not accessible by clients), there should be no need to lock
1908 List<SceneObjectPart> partsList = new List<SceneObjectPart>(m_parts.Values);
1909 m_parts.Clear();
1910 foreach (SceneObjectPart part in partsList)
1911 { 1923 {
1912 part.ResetIDs(part.LinkNum); // Don't change link nums 1924 List<SceneObjectPart> partsList = new List<SceneObjectPart>(m_parts.Values);
1913 m_parts.Add(part.UUID, part); 1925 m_parts.Clear();
1926 foreach (SceneObjectPart part in partsList)
1927 {
1928 part.ResetIDs(part.LinkNum); // Don't change link nums
1929 m_parts.Add(part.UUID, part);
1930 }
1914 } 1931 }
1915 } 1932 }
1916 1933
@@ -2136,10 +2153,15 @@ namespace OpenSim.Region.Framework.Scenes
2136 public SceneObjectPart GetChildPart(UUID primID) 2153 public SceneObjectPart GetChildPart(UUID primID)
2137 { 2154 {
2138 SceneObjectPart childPart = null; 2155 SceneObjectPart childPart = null;
2139 if (m_parts.ContainsKey(primID)) 2156
2157 lock (m_parts)
2140 { 2158 {
2141 childPart = m_parts[primID]; 2159 if (m_parts.ContainsKey(primID))
2160 {
2161 childPart = m_parts[primID];
2162 }
2142 } 2163 }
2164
2143 return childPart; 2165 return childPart;
2144 } 2166 }
2145 2167
@@ -2174,9 +2196,10 @@ namespace OpenSim.Region.Framework.Scenes
2174 /// <returns></returns> 2196 /// <returns></returns>
2175 public bool HasChildPrim(UUID primID) 2197 public bool HasChildPrim(UUID primID)
2176 { 2198 {
2177 if (m_parts.ContainsKey(primID)) 2199 lock (m_parts)
2178 { 2200 {
2179 return true; 2201 if (m_parts.ContainsKey(primID))
2202 return true;
2180 } 2203 }
2181 2204
2182 return false; 2205 return false;
@@ -2370,17 +2393,19 @@ namespace OpenSim.Region.Framework.Scenes
2370 lock (m_parts) 2393 lock (m_parts)
2371 { 2394 {
2372 m_parts.Remove(linkPart.UUID); 2395 m_parts.Remove(linkPart.UUID);
2373 } 2396
2374 2397 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2375 if (m_parts.Count == 1 && RootPart != null) //Single prim is left
2376 RootPart.LinkNum = 0;
2377 else
2378 {
2379 foreach (SceneObjectPart p in m_parts.Values)
2380 { 2398 {
2381 if (p.LinkNum > linkPart.LinkNum) 2399 RootPart.LinkNum = 0;
2382 p.LinkNum--;
2383 } 2400 }
2401 else
2402 {
2403 foreach (SceneObjectPart p in m_parts.Values)
2404 {
2405 if (p.LinkNum > linkPart.LinkNum)
2406 p.LinkNum--;
2407 }
2408 }
2384 } 2409 }
2385 2410
2386 linkPart.ParentID = 0; 2411 linkPart.ParentID = 0;
@@ -2762,9 +2787,11 @@ namespace OpenSim.Region.Framework.Scenes
2762 public void UpdatePermissions(UUID AgentID, byte field, uint localID, 2787 public void UpdatePermissions(UUID AgentID, byte field, uint localID,
2763 uint mask, byte addRemTF) 2788 uint mask, byte addRemTF)
2764 { 2789 {
2765 foreach (SceneObjectPart part in m_parts.Values) 2790 lock (m_parts)
2766 part.UpdatePermissions(AgentID, field, localID, mask, 2791 {
2767 addRemTF); 2792 foreach (SceneObjectPart part in m_parts.Values)
2793 part.UpdatePermissions(AgentID, field, localID, mask, addRemTF);
2794 }
2768 2795
2769 HasGroupChanged = true; 2796 HasGroupChanged = true;
2770 } 2797 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 84b7365..e08fa77 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -601,7 +601,10 @@ namespace OpenSim.Region.Framework.Scenes
601 rootPart.Name = item.Name; 601 rootPart.Name = item.Name;
602 rootPart.Description = item.Description; 602 rootPart.Description = item.Description;
603 603
604 List<SceneObjectPart> partList = new List<SceneObjectPart>(group.Children.Values); 604 List<SceneObjectPart> partList = null;
605
606 lock (group.Children)
607 partList = new List<SceneObjectPart>(group.Children.Values);
605 608
606 group.SetGroup(m_part.GroupID, null); 609 group.SetGroup(m_part.GroupID, null);
607 610