diff options
author | Justin Clark-Casey (justincc) | 2011-09-06 22:26:28 +0100 |
---|---|---|
committer | Justin Clark-Casey (justincc) | 2011-09-06 22:26:28 +0100 |
commit | 4bf3adffb8d58a7a856307df3460ac3eb4bf6d91 (patch) | |
tree | b7e99547d70afdc49cf6993db24c935f9781945f | |
parent | refactor: Make logic in AM.AttachObject() clearer by not reusing existing var... (diff) | |
download | opensim-SC-4bf3adffb8d58a7a856307df3460ac3eb4bf6d91.zip opensim-SC-4bf3adffb8d58a7a856307df3460ac3eb4bf6d91.tar.gz opensim-SC-4bf3adffb8d58a7a856307df3460ac3eb4bf6d91.tar.bz2 opensim-SC-4bf3adffb8d58a7a856307df3460ac3eb4bf6d91.tar.xz |
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
-rw-r--r-- | OpenSim/Region/Framework/Interfaces/ISceneViewer.cs | 11 | ||||
-rw-r--r-- | OpenSim/Region/Framework/Scenes/SceneViewer.cs | 59 |
2 files changed, 51 insertions, 19 deletions
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; | |||
30 | 30 | ||
31 | namespace OpenSim.Region.Framework.Interfaces | 31 | namespace OpenSim.Region.Framework.Interfaces |
32 | { | 32 | { |
33 | /// <summary> | ||
34 | /// Sends scheduled updates to it's associated ScenePresence. | ||
35 | /// </summary> | ||
33 | public interface ISceneViewer | 36 | public interface ISceneViewer |
34 | { | 37 | { |
35 | void Reset(); | 38 | void Reset(); |
36 | void Close(); | 39 | void Close(); |
40 | |||
41 | /// <summary> | ||
42 | /// Add the part to the queue of parts for which we need to send an update to the client | ||
43 | /// </summary> | ||
44 | /// <param name="part"></param> | ||
37 | void QueuePartForUpdate(SceneObjectPart part); | 45 | void QueuePartForUpdate(SceneObjectPart part); |
46 | |||
38 | void SendPrimUpdates(); | 47 | void SendPrimUpdates(); |
39 | int GetPendingObjectsCount(); | 48 | int GetPendingObjectsCount(); |
40 | } | 49 | } |
41 | } | 50 | } \ 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 | |||
38 | { | 38 | { |
39 | public class SceneViewer : ISceneViewer | 39 | public class SceneViewer : ISceneViewer |
40 | { | 40 | { |
41 | /// <summary> | ||
42 | /// Is this scene viewer enabled? | ||
43 | /// </summary> | ||
44 | private bool IsEnabled { get; set; } | ||
45 | |||
46 | /// <summary> | ||
47 | /// The scene presence serviced by this viewer. | ||
48 | /// </summary> | ||
41 | protected ScenePresence m_presence; | 49 | protected ScenePresence m_presence; |
50 | |||
51 | /// <summary> | ||
52 | /// The queue of parts for which we need to send out updates. | ||
53 | /// </summary> | ||
42 | protected UpdateQueue m_partsUpdateQueue = new UpdateQueue(); | 54 | protected UpdateQueue m_partsUpdateQueue = new UpdateQueue(); |
55 | |||
56 | /// <summary> | ||
57 | /// The queue of objects for which we need to send out updates. | ||
58 | /// </summary> | ||
43 | protected Queue<SceneObjectGroup> m_pendingObjects; | 59 | protected Queue<SceneObjectGroup> m_pendingObjects; |
44 | 60 | ||
61 | /// <summary> | ||
62 | /// The last update assocated with a given part update. | ||
63 | /// </summary> | ||
45 | protected Dictionary<UUID, ScenePartUpdate> m_updateTimes = new Dictionary<UUID, ScenePartUpdate>(); | 64 | protected Dictionary<UUID, ScenePartUpdate> m_updateTimes = new Dictionary<UUID, ScenePartUpdate>(); |
46 | 65 | ||
47 | public SceneViewer() | ||
48 | { | ||
49 | } | ||
50 | |||
51 | public SceneViewer(ScenePresence presence) | 66 | public SceneViewer(ScenePresence presence) |
52 | { | 67 | { |
53 | m_presence = presence; | 68 | m_presence = presence; |
69 | IsEnabled = true; | ||
54 | } | 70 | } |
55 | 71 | ||
56 | /// <summary> | ||
57 | /// Add the part to the queue of parts for which we need to send an update to the client | ||
58 | /// </summary> | ||
59 | /// <param name="part"></param> | ||
60 | public void QueuePartForUpdate(SceneObjectPart part) | 72 | public void QueuePartForUpdate(SceneObjectPart part) |
61 | { | 73 | { |
74 | if (!IsEnabled) | ||
75 | return; | ||
76 | |||
62 | lock (m_partsUpdateQueue) | 77 | lock (m_partsUpdateQueue) |
63 | { | 78 | { |
64 | m_partsUpdateQueue.Enqueue(part); | 79 | m_partsUpdateQueue.Enqueue(part); |
@@ -87,6 +102,11 @@ namespace OpenSim.Region.Framework.Scenes | |||
87 | 102 | ||
88 | lock (m_pendingObjects) | 103 | lock (m_pendingObjects) |
89 | { | 104 | { |
105 | // We must do this under lock so that we don't suffer a race condition if another thread closes the | ||
106 | // viewer | ||
107 | if (!IsEnabled) | ||
108 | return; | ||
109 | |||
90 | while (m_pendingObjects != null && m_pendingObjects.Count > 0) | 110 | while (m_pendingObjects != null && m_pendingObjects.Count > 0) |
91 | { | 111 | { |
92 | SceneObjectGroup g = m_pendingObjects.Dequeue(); | 112 | SceneObjectGroup g = m_pendingObjects.Dequeue(); |
@@ -119,7 +139,6 @@ namespace OpenSim.Region.Framework.Scenes | |||
119 | 139 | ||
120 | // We deal with the possibility that two updates occur at | 140 | // We deal with the possibility that two updates occur at |
121 | // the same unix time at the update point itself. | 141 | // the same unix time at the update point itself. |
122 | |||
123 | if ((update.LastFullUpdateTime < part.TimeStampFull) || part.ParentGroup.IsAttachment) | 142 | if ((update.LastFullUpdateTime < part.TimeStampFull) || part.ParentGroup.IsAttachment) |
124 | { | 143 | { |
125 | // m_log.DebugFormat( | 144 | // m_log.DebugFormat( |
@@ -135,9 +154,7 @@ namespace OpenSim.Region.Framework.Scenes | |||
135 | // this update. If this happened, then subsequent | 154 | // this update. If this happened, then subsequent |
136 | // updates which occurred on the same tick or the | 155 | // updates which occurred on the same tick or the |
137 | // next tick of the last update would be ignored. | 156 | // next tick of the last update would be ignored. |
138 | |||
139 | update.LastFullUpdateTime = part.TimeStampFull; | 157 | update.LastFullUpdateTime = part.TimeStampFull; |
140 | |||
141 | } | 158 | } |
142 | else if (update.LastTerseUpdateTime <= part.TimeStampTerse) | 159 | else if (update.LastTerseUpdateTime <= part.TimeStampTerse) |
143 | { | 160 | { |
@@ -193,15 +210,21 @@ namespace OpenSim.Region.Framework.Scenes | |||
193 | 210 | ||
194 | public void Close() | 211 | public void Close() |
195 | { | 212 | { |
196 | lock (m_updateTimes) | 213 | lock (m_pendingObjects) |
197 | { | ||
198 | m_updateTimes.Clear(); | ||
199 | } | ||
200 | lock (m_partsUpdateQueue) | ||
201 | { | 214 | { |
202 | m_partsUpdateQueue.Clear(); | 215 | IsEnabled = false; |
216 | |||
217 | lock (m_updateTimes) | ||
218 | { | ||
219 | m_updateTimes.Clear(); | ||
220 | } | ||
221 | lock (m_partsUpdateQueue) | ||
222 | { | ||
223 | m_partsUpdateQueue.Clear(); | ||
224 | } | ||
225 | |||
226 | Reset(); | ||
203 | } | 227 | } |
204 | Reset(); | ||
205 | } | 228 | } |
206 | 229 | ||
207 | public int GetPendingObjectsCount() | 230 | public int GetPendingObjectsCount() |