From c77728ebf86014f41eb5ae6b325af4079063a971 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 13 Dec 2012 21:02:55 +0000 Subject: [PATCH] Add WaitForEventCompletionOnScriptStop [XEngine] config param to OpenSimDefaults.ini to allow change of the wait time for an event to complete on script removal before aborting its thread Default is 1000, as has previously been the case. This parameter exists for further debug work concerning mono 2.10 crashes that may be related to locks not being removed on Thread.Abort --- .../Region/ScriptEngine/XEngine/XEngine.cs | 34 +++++++++++++------ bin/OpenSimDefaults.ini | 4 +++ 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 00f84c5641..d554656b5a 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; @@ -1688,16 +1707,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 b2c52e3ae2..c3d129464d 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -1367,6 +1367,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