diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 828f2fbfb4..1dd50c7a40 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -107,6 +107,24 @@ namespace OpenSim.Region.ScriptEngine.XEngine private IXmlRpcRouter m_XmlRpcRouter; private int m_EventLimit; private bool m_KillTimedOutScripts; + + /// + /// Number of milliseconds we will wait for a script event to complete on script stop before we forcibly abort + /// its thread. + /// + /// + /// It appears that if a script thread is aborted whilst it is holding ReaderWriterLockSlim (possibly the write + /// lock) then the lock is not properly released. This causes mono 2.6, 2.10 and possibly + /// later to crash, sometimes with symptoms such as a leap to 100% script usage and a vm thead dump showing + /// all threads waiting on release of ReaderWriterLockSlim write thread which none of the threads listed + /// actually hold. + /// + /// Pausing for event completion reduces the risk of this happening. However, it may be that aborting threads + /// is not a mono issue per se but rather a risky activity in itself in an AppDomain that is not immediately + /// shutting down. + /// + private int m_WaitForEventCompletionOnScriptStop = 1000; + private string m_ScriptEnginesPath = null; private ExpiringCache m_runFlags = new ExpiringCache(); @@ -249,6 +267,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine m_EventLimit = m_ScriptConfig.GetInt("EventLimit", 30); m_KillTimedOutScripts = m_ScriptConfig.GetBoolean("KillTimedOutScripts", false); m_SaveTime = m_ScriptConfig.GetInt("SaveInterval", 120) * 1000; + m_WaitForEventCompletionOnScriptStop + = m_ScriptConfig.GetInt("WaitForEventCompletionOnScriptStop", m_WaitForEventCompletionOnScriptStop); + m_ScriptEnginesPath = m_ScriptConfig.GetString("ScriptEnginesPath", "ScriptEngines"); m_Prio = ThreadPriority.BelowNormal; @@ -1335,9 +1356,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine instance.ClearQueue(); - // Give the script some time to finish processing its last event. Simply aborting the script thread can - // cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort. - instance.Stop(1000); + instance.Stop(m_WaitForEventCompletionOnScriptStop); // bool objectRemoved = false; @@ -1687,16 +1706,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine public void StopScript(UUID itemID) { IScriptInstance instance = GetInstance(itemID); + if (instance != null) - { - // Give the script some time to finish processing its last event. Simply aborting the script thread can - // cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort. - instance.Stop(1000); - } + instance.Stop(m_WaitForEventCompletionOnScriptStop); else - { m_runFlags.AddOrUpdate(itemID, false, 240); - } } public DetectParams GetDetectParams(UUID itemID, int idx) diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index e9bdabc7fe..284adfe387 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -1368,6 +1368,10 @@ ; If a script overruns it's event limit, kill the script? KillTimedOutScripts = false + ; Amount of time in milliseconds we will wait for an event to completely normally when a script stop is requested + ; before aborting the thread (such as when an object containing scripts is taken into inventory). + WaitForEventCompletionOnScriptStop = 1000; + ; Sets the multiplier for the scripting delays ScriptDelayFactor = 1.0