aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Shared
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2012-07-31 23:57:57 +0100
committerJustin Clark-Casey (justincc)2012-07-31 23:57:57 +0100
commit7609daca388d1acbe8da7eaf407c0b3f4da1fd80 (patch)
treefaaf03a514ab3227270cb83cdfb1d2c5a938714d /OpenSim/Region/ScriptEngine/Shared
parentFix bug in SoundModule.TriggerSound() where every sound update to an avatar w... (diff)
downloadopensim-SC_OLD-7609daca388d1acbe8da7eaf407c0b3f4da1fd80.zip
opensim-SC_OLD-7609daca388d1acbe8da7eaf407c0b3f4da1fd80.tar.gz
opensim-SC_OLD-7609daca388d1acbe8da7eaf407c0b3f4da1fd80.tar.bz2
opensim-SC_OLD-7609daca388d1acbe8da7eaf407c0b3f4da1fd80.tar.xz
Resolve a deadlock between INPCModule and SensorRepeat by replacing the SensorRepeat list with a new list on add/removes rather than locking it for the duration of the sensor sweep.
A deadlock was observed today where NPC removal on a script thread would lock the NPC list and then try to lock the sensor list via scripted attachment removal. Concurrently, the sensor sweep thread would lock the sensor list and then try to lock the NPC list to check NPC status. This commit resolves the deadlock by replacing the sensor list on update rather than locking it for the duration of the sweep.
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Shared')
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs78
1 files changed, 43 insertions, 35 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
index f2c8b60..06495bb 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
@@ -51,8 +51,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
51 { 51 {
52 get 52 get
53 { 53 {
54 lock (SenseRepeatListLock) 54 return SenseRepeaters.Count;
55 return SenseRepeaters.Count;
56 } 55 }
57 } 56 }
58 57
@@ -116,6 +115,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
116 public double distance; 115 public double distance;
117 } 116 }
118 117
118 /// <summary>
119 /// Sensors to process.
120 /// </summary>
121 /// <remarks>
122 /// Do not add or remove sensors from this list directly. Instead, copy the list and substitute the updated
123 /// copy. This is to avoid locking the list for the duration of the sensor sweep, which increases the danger
124 /// of deadlocks with future code updates.
125 ///
126 /// Always lock SenseRepeatListLock when updating this list.
127 /// </remarks>
119 private List<SenseRepeatClass> SenseRepeaters = new List<SenseRepeatClass>(); 128 private List<SenseRepeatClass> SenseRepeaters = new List<SenseRepeatClass>();
120 private object SenseRepeatListLock = new object(); 129 private object SenseRepeatListLock = new object();
121 130
@@ -125,6 +134,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
125 { 134 {
126 // Always remove first, in case this is a re-set 135 // Always remove first, in case this is a re-set
127 UnSetSenseRepeaterEvents(m_localID, m_itemID); 136 UnSetSenseRepeaterEvents(m_localID, m_itemID);
137
128 if (sec == 0) // Disabling timer 138 if (sec == 0) // Disabling timer
129 return; 139 return;
130 140
@@ -144,9 +154,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
144 ts.host = host; 154 ts.host = host;
145 155
146 ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); 156 ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
157
158 AddSenseRepeater(ts);
159 }
160
161 private void AddSenseRepeater(SenseRepeatClass senseRepeater)
162 {
147 lock (SenseRepeatListLock) 163 lock (SenseRepeatListLock)
148 { 164 {
149 SenseRepeaters.Add(ts); 165 List<SenseRepeatClass> newSenseRepeaters = new List<SenseRepeatClass>(SenseRepeaters);
166 newSenseRepeaters.Add(senseRepeater);
167 SenseRepeaters = newSenseRepeaters;
150 } 168 }
151 } 169 }
152 170
@@ -155,39 +173,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
155 // Remove from timer 173 // Remove from timer
156 lock (SenseRepeatListLock) 174 lock (SenseRepeatListLock)
157 { 175 {
158 List<SenseRepeatClass> NewSensors = new List<SenseRepeatClass>(); 176 List<SenseRepeatClass> newSenseRepeaters = new List<SenseRepeatClass>();
159 foreach (SenseRepeatClass ts in SenseRepeaters) 177 foreach (SenseRepeatClass ts in SenseRepeaters)
160 { 178 {
161 if (ts.localID != m_localID || ts.itemID != m_itemID) 179 if (ts.localID != m_localID || ts.itemID != m_itemID)
162 { 180 {
163 NewSensors.Add(ts); 181 newSenseRepeaters.Add(ts);
164 } 182 }
165 } 183 }
166 SenseRepeaters.Clear(); 184
167 SenseRepeaters = NewSensors; 185 SenseRepeaters = newSenseRepeaters;
168 } 186 }
169 } 187 }
170 188
171 public void CheckSenseRepeaterEvents() 189 public void CheckSenseRepeaterEvents()
172 { 190 {
173 lock (SenseRepeatListLock) 191 // Go through all timers
192 foreach (SenseRepeatClass ts in SenseRepeaters)
174 { 193 {
175 // Nothing to do here? 194 // Time has passed?
176 if (SenseRepeaters.Count == 0) 195 if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime())
177 return;
178
179 // Go through all timers
180 foreach (SenseRepeatClass ts in SenseRepeaters)
181 { 196 {
182 // Time has passed? 197 SensorSweep(ts);
183 if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime()) 198 // set next interval
184 { 199 ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
185 SensorSweep(ts);
186 // set next interval
187 ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
188 }
189 } 200 }
190 } // lock 201 }
191 } 202 }
192 203
193 public void SenseOnce(uint m_localID, UUID m_itemID, 204 public void SenseOnce(uint m_localID, UUID m_itemID,
@@ -615,21 +626,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
615 { 626 {
616 List<Object> data = new List<Object>(); 627 List<Object> data = new List<Object>();
617 628
618 lock (SenseRepeatListLock) 629 foreach (SenseRepeatClass ts in SenseRepeaters)
619 { 630 {
620 foreach (SenseRepeatClass ts in SenseRepeaters) 631 if (ts.itemID == itemID)
621 { 632 {
622 if (ts.itemID == itemID) 633 data.Add(ts.interval);
623 { 634 data.Add(ts.name);
624 data.Add(ts.interval); 635 data.Add(ts.keyID);
625 data.Add(ts.name); 636 data.Add(ts.type);
626 data.Add(ts.keyID); 637 data.Add(ts.range);
627 data.Add(ts.type); 638 data.Add(ts.arc);
628 data.Add(ts.range);
629 data.Add(ts.arc);
630 }
631 } 639 }
632 } 640 }
641
633 return data.ToArray(); 642 return data.ToArray();
634 } 643 }
635 644
@@ -663,8 +672,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
663 ts.next = 672 ts.next =
664 DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); 673 DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
665 674
666 lock (SenseRepeatListLock) 675 AddSenseRepeater(ts);
667 SenseRepeaters.Add(ts);
668 676
669 idx += 6; 677 idx += 6;
670 } 678 }