diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
index f2c8b6085a..06495bb1ba 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
{
get
{
- lock (SenseRepeatListLock)
- return SenseRepeaters.Count;
+ return SenseRepeaters.Count;
}
}
@@ -116,6 +115,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
public double distance;
}
+ ///
+ /// Sensors to process.
+ ///
+ ///
+ /// Do not add or remove sensors from this list directly. Instead, copy the list and substitute the updated
+ /// copy. This is to avoid locking the list for the duration of the sensor sweep, which increases the danger
+ /// of deadlocks with future code updates.
+ ///
+ /// Always lock SenseRepeatListLock when updating this list.
+ ///
private List SenseRepeaters = new List();
private object SenseRepeatListLock = new object();
@@ -125,6 +134,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
{
// Always remove first, in case this is a re-set
UnSetSenseRepeaterEvents(m_localID, m_itemID);
+
if (sec == 0) // Disabling timer
return;
@@ -144,9 +154,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
ts.host = host;
ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
+
+ AddSenseRepeater(ts);
+ }
+
+ private void AddSenseRepeater(SenseRepeatClass senseRepeater)
+ {
lock (SenseRepeatListLock)
{
- SenseRepeaters.Add(ts);
+ List newSenseRepeaters = new List(SenseRepeaters);
+ newSenseRepeaters.Add(senseRepeater);
+ SenseRepeaters = newSenseRepeaters;
}
}
@@ -155,39 +173,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
// Remove from timer
lock (SenseRepeatListLock)
{
- List NewSensors = new List();
+ List newSenseRepeaters = new List();
foreach (SenseRepeatClass ts in SenseRepeaters)
{
if (ts.localID != m_localID || ts.itemID != m_itemID)
{
- NewSensors.Add(ts);
+ newSenseRepeaters.Add(ts);
}
}
- SenseRepeaters.Clear();
- SenseRepeaters = NewSensors;
+
+ SenseRepeaters = newSenseRepeaters;
}
}
public void CheckSenseRepeaterEvents()
{
- lock (SenseRepeatListLock)
+ // Go through all timers
+ foreach (SenseRepeatClass ts in SenseRepeaters)
{
- // Nothing to do here?
- if (SenseRepeaters.Count == 0)
- return;
-
- // Go through all timers
- foreach (SenseRepeatClass ts in SenseRepeaters)
+ // Time has passed?
+ if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime())
{
- // Time has passed?
- if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime())
- {
- SensorSweep(ts);
- // set next interval
- ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
- }
+ SensorSweep(ts);
+ // set next interval
+ ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
}
- } // lock
+ }
}
public void SenseOnce(uint m_localID, UUID m_itemID,
@@ -615,21 +626,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
{
List