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 --- OpenSim/Region/Framework/Scenes/SceneViewer.cs | 59 ++++++++++++++++++-------- 1 file changed, 41 insertions(+), 18 deletions(-) (limited to 'OpenSim/Region/Framework/Scenes') 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