aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2011-09-06 22:26:28 +0100
committerJustin Clark-Casey (justincc)2011-09-06 22:26:28 +0100
commit4bf3adffb8d58a7a856307df3460ac3eb4bf6d91 (patch)
treeb7e99547d70afdc49cf6993db24c935f9781945f
parentrefactor: Make logic in AM.AttachObject() clearer by not reusing existing var... (diff)
downloadopensim-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.cs11
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneViewer.cs59
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
31namespace OpenSim.Region.Framework.Interfaces 31namespace 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()