From 9784e4e07db63a23897876dfbd27974878d5eca9 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Thu, 9 Aug 2012 14:51:05 +0300 Subject: Changed locks to prevent deadlocks (especially during multi-region Load OAR) --- .../World/Archiver/ArchiveReadRequest.cs | 42 ++++++++++++------- .../CoreModules/World/Land/LandManagementModule.cs | 47 +++++++++++++--------- .../CoreModules/World/Land/PrimCountModule.cs | 11 +++-- 3 files changed, 61 insertions(+), 39 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index c810242..32d245f 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -604,13 +604,18 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// private bool ResolveUserUuid(Scene scene, UUID uuid) { - if (!m_validUserUuids.ContainsKey(uuid)) + lock (m_validUserUuids) { - UserAccount account = scene.UserAccountService.GetUserAccount(scene.RegionInfo.ScopeID, uuid); - m_validUserUuids.Add(uuid, account != null); - } + if (!m_validUserUuids.ContainsKey(uuid)) + { + // Note: we call GetUserAccount() inside the lock because this UserID is likely + // to occur many times, and we only want to query the users service once. + UserAccount account = scene.UserAccountService.GetUserAccount(scene.RegionInfo.ScopeID, uuid); + m_validUserUuids.Add(uuid, account != null); + } - return m_validUserUuids[uuid]; + return m_validUserUuids[uuid]; + } } /// @@ -623,19 +628,26 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (uuid == UUID.Zero) return true; // this means the object has no group - if (!m_validGroupUuids.ContainsKey(uuid)) + lock (m_validGroupUuids) { - bool exists; - - if (m_groupsModule == null) - exists = false; - else - exists = (m_groupsModule.GetGroupRecord(uuid) != null); + if (!m_validGroupUuids.ContainsKey(uuid)) + { + bool exists; + if (m_groupsModule == null) + { + exists = false; + } + else + { + // Note: we call GetGroupRecord() inside the lock because this GroupID is likely + // to occur many times, and we only want to query the groups service once. + exists = (m_groupsModule.GetGroupRecord(uuid) != null); + } + m_validGroupUuids.Add(uuid, exists); + } - m_validGroupUuids.Add(uuid, exists); + return m_validGroupUuids[uuid]; } - - return m_validGroupUuids[uuid]; } /// Load an asset diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index e85b7a2..4b1e6b9 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -287,14 +287,15 @@ namespace OpenSim.Region.CoreModules.World.Land LandData newData = data.Copy(); newData.LocalID = local_id; + ILandObject land; lock (m_landList) { - if (m_landList.ContainsKey(local_id)) - { - m_landList[local_id].LandData = newData; - m_scene.EventManager.TriggerLandObjectUpdated((uint)local_id, m_landList[local_id]); - } + if (m_landList.TryGetValue(local_id, out land)) + land.LandData = newData; } + + if (land != null) + m_scene.EventManager.TriggerLandObjectUpdated((uint)local_id, land); } public bool AllowedForcefulBans @@ -613,7 +614,7 @@ namespace OpenSim.Region.CoreModules.World.Land // Only now can we add the prim counts to the land object - we rely on the global ID which is generated // as a random UUID inside LandData initialization if (m_primCountModule != null) - new_land.PrimCounts = m_primCountModule.GetPrimCounts(new_land.LandData.GlobalID); + new_land.PrimCounts = m_primCountModule.GetPrimCounts(new_land.LandData.GlobalID); lock (m_landList) { @@ -650,6 +651,7 @@ namespace OpenSim.Region.CoreModules.World.Land /// Land.localID of the peice of land to remove. public void removeLandObject(int local_id) { + ILandObject land; lock (m_landList) { for (int x = 0; x < 64; x++) @@ -666,9 +668,11 @@ namespace OpenSim.Region.CoreModules.World.Land } } - m_scene.EventManager.TriggerLandObjectRemoved(m_landList[local_id].LandData.GlobalID); + land = m_landList[local_id]; m_landList.Remove(local_id); } + + m_scene.EventManager.TriggerLandObjectRemoved(land.LandData.GlobalID); } /// @@ -676,21 +680,27 @@ namespace OpenSim.Region.CoreModules.World.Land /// public void Clear(bool setupDefaultParcel) { + List parcels; lock (m_landList) { - foreach (ILandObject lo in m_landList.Values) - { - //m_scene.SimulationDataService.RemoveLandObject(lo.LandData.GlobalID); - m_scene.EventManager.TriggerLandObjectRemoved(lo.LandData.GlobalID); - } + parcels = new List(m_landList.Values); + } + + foreach (ILandObject lo in parcels) + { + //m_scene.SimulationDataService.RemoveLandObject(lo.LandData.GlobalID); + m_scene.EventManager.TriggerLandObjectRemoved(lo.LandData.GlobalID); + } + lock (m_landList) + { m_landList.Clear(); ResetSimLandObjects(); - - if (setupDefaultParcel) - CreateDefaultParcel(); } + + if (setupDefaultParcel) + CreateDefaultParcel(); } private void performFinalLandJoin(ILandObject master, ILandObject slave) @@ -1458,11 +1468,8 @@ namespace OpenSim.Region.CoreModules.World.Land public void EventManagerOnNoLandDataFromStorage() { - lock (m_landList) - { - ResetSimLandObjects(); - CreateDefaultParcel(); - } + ResetSimLandObjects(); + CreateDefaultParcel(); } #endregion diff --git a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs index f9cc0cf..9b51cc8 100644 --- a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs @@ -490,11 +490,14 @@ namespace OpenSim.Region.CoreModules.World.Land m_Scene.ForEachSOG(AddObject); - List primcountKeys = new List(m_PrimCounts.Keys); - foreach (UUID k in primcountKeys) + lock (m_PrimCounts) { - if (!m_OwnerMap.ContainsKey(k)) - m_PrimCounts.Remove(k); + List primcountKeys = new List(m_PrimCounts.Keys); + foreach (UUID k in primcountKeys) + { + if (!m_OwnerMap.ContainsKey(k)) + m_PrimCounts.Remove(k); + } } m_Tainted = false; -- cgit v1.1