From 4bf3adffb8d58a7a856307df3460ac3eb4bf6d91 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Tue, 6 Sep 2011 22:26:28 +0100 Subject: In SceneViewer, introduce an IsEnabled flag and perform Close() under an m_pendingObjects lock in order to avoid the race condition seen by danbanner in http://opensimulator.org/mantis/view.php?id=5669 --- .../Region/Framework/Interfaces/ISceneViewer.cs | 11 +++- OpenSim/Region/Framework/Scenes/SceneViewer.cs | 59 +++++++++++++++------- 2 files changed, 51 insertions(+), 19 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/Framework/Interfaces/ISceneViewer.cs b/OpenSim/Region/Framework/Interfaces/ISceneViewer.cs index 2397f22..a4cc2be 100644 --- a/OpenSim/Region/Framework/Interfaces/ISceneViewer.cs +++ b/OpenSim/Region/Framework/Interfaces/ISceneViewer.cs @@ -30,12 +30,21 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.Framework.Interfaces { + /// + /// Sends scheduled updates to it's associated ScenePresence. + /// public interface ISceneViewer { void Reset(); void Close(); + + /// + /// Add the part to the queue of parts for which we need to send an update to the client + /// + /// void QueuePartForUpdate(SceneObjectPart part); + void SendPrimUpdates(); int GetPendingObjectsCount(); } -} +} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/SceneViewer.cs b/OpenSim/Region/Framework/Scenes/SceneViewer.cs index e2ea830..3e0d1db 100644 --- a/OpenSim/Region/Framework/Scenes/SceneViewer.cs +++ b/OpenSim/Region/Framework/Scenes/SceneViewer.cs @@ -38,27 +38,42 @@ namespace OpenSim.Region.Framework.Scenes { public class SceneViewer : ISceneViewer { + /// + /// Is this scene viewer enabled? + /// + private bool IsEnabled { get; set; } + + /// + /// The scene presence serviced by this viewer. + /// protected ScenePresence m_presence; + + /// + /// The queue of parts for which we need to send out updates. + /// protected UpdateQueue m_partsUpdateQueue = new UpdateQueue(); + + /// + /// The queue of objects for which we need to send out updates. + /// protected Queue m_pendingObjects; + /// + /// The last update assocated with a given part update. + /// protected Dictionary m_updateTimes = new Dictionary(); - public SceneViewer() - { - } - public SceneViewer(ScenePresence presence) { m_presence = presence; + IsEnabled = true; } - /// - /// Add the part to the queue of parts for which we need to send an update to the client - /// - /// public void QueuePartForUpdate(SceneObjectPart part) { + if (!IsEnabled) + return; + lock (m_partsUpdateQueue) { m_partsUpdateQueue.Enqueue(part); @@ -87,6 +102,11 @@ namespace OpenSim.Region.Framework.Scenes lock (m_pendingObjects) { + // We must do this under lock so that we don't suffer a race condition if another thread closes the + // viewer + if (!IsEnabled) + return; + while (m_pendingObjects != null && m_pendingObjects.Count > 0) { SceneObjectGroup g = m_pendingObjects.Dequeue(); @@ -119,7 +139,6 @@ namespace OpenSim.Region.Framework.Scenes // We deal with the possibility that two updates occur at // the same unix time at the update point itself. - if ((update.LastFullUpdateTime < part.TimeStampFull) || part.ParentGroup.IsAttachment) { // m_log.DebugFormat( @@ -135,9 +154,7 @@ namespace OpenSim.Region.Framework.Scenes // this update. If this happened, then subsequent // updates which occurred on the same tick or the // next tick of the last update would be ignored. - update.LastFullUpdateTime = part.TimeStampFull; - } else if (update.LastTerseUpdateTime <= part.TimeStampTerse) { @@ -193,15 +210,21 @@ namespace OpenSim.Region.Framework.Scenes public void Close() { - lock (m_updateTimes) - { - m_updateTimes.Clear(); - } - lock (m_partsUpdateQueue) + lock (m_pendingObjects) { - m_partsUpdateQueue.Clear(); + IsEnabled = false; + + lock (m_updateTimes) + { + m_updateTimes.Clear(); + } + lock (m_partsUpdateQueue) + { + m_partsUpdateQueue.Clear(); + } + + Reset(); } - Reset(); } public int GetPendingObjectsCount() -- cgit v1.1