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
0.7.4-extended
Justin Clark-Casey (justincc) 2012-12-13 21:02:55 +00:00
parent 83487bfbec
commit c77728ebf8
2 changed files with 28 additions and 10 deletions

View File

@ -107,6 +107,24 @@ namespace OpenSim.Region.ScriptEngine.XEngine
private IXmlRpcRouter m_XmlRpcRouter; private IXmlRpcRouter m_XmlRpcRouter;
private int m_EventLimit; private int m_EventLimit;
private bool m_KillTimedOutScripts; private bool m_KillTimedOutScripts;
/// <summary>
/// Number of milliseconds we will wait for a script event to complete on script stop before we forcibly abort
/// its thread.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
private int m_WaitForEventCompletionOnScriptStop = 1000;
private string m_ScriptEnginesPath = null; private string m_ScriptEnginesPath = null;
private ExpiringCache<UUID, bool> m_runFlags = new ExpiringCache<UUID, bool>(); private ExpiringCache<UUID, bool> m_runFlags = new ExpiringCache<UUID, bool>();
@ -249,6 +267,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
m_EventLimit = m_ScriptConfig.GetInt("EventLimit", 30); m_EventLimit = m_ScriptConfig.GetInt("EventLimit", 30);
m_KillTimedOutScripts = m_ScriptConfig.GetBoolean("KillTimedOutScripts", false); m_KillTimedOutScripts = m_ScriptConfig.GetBoolean("KillTimedOutScripts", false);
m_SaveTime = m_ScriptConfig.GetInt("SaveInterval", 120) * 1000; m_SaveTime = m_ScriptConfig.GetInt("SaveInterval", 120) * 1000;
m_WaitForEventCompletionOnScriptStop
= m_ScriptConfig.GetInt("WaitForEventCompletionOnScriptStop", m_WaitForEventCompletionOnScriptStop);
m_ScriptEnginesPath = m_ScriptConfig.GetString("ScriptEnginesPath", "ScriptEngines"); m_ScriptEnginesPath = m_ScriptConfig.GetString("ScriptEnginesPath", "ScriptEngines");
m_Prio = ThreadPriority.BelowNormal; m_Prio = ThreadPriority.BelowNormal;
@ -1335,9 +1356,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
instance.ClearQueue(); instance.ClearQueue();
// Give the script some time to finish processing its last event. Simply aborting the script thread can instance.Stop(m_WaitForEventCompletionOnScriptStop);
// cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort.
instance.Stop(1000);
// bool objectRemoved = false; // bool objectRemoved = false;
@ -1688,17 +1707,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
public void StopScript(UUID itemID) public void StopScript(UUID itemID)
{ {
IScriptInstance instance = GetInstance(itemID); IScriptInstance instance = GetInstance(itemID);
if (instance != null) if (instance != null)
{ instance.Stop(m_WaitForEventCompletionOnScriptStop);
// 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);
}
else else
{
m_runFlags.AddOrUpdate(itemID, false, 240); m_runFlags.AddOrUpdate(itemID, false, 240);
} }
}
public DetectParams GetDetectParams(UUID itemID, int idx) public DetectParams GetDetectParams(UUID itemID, int idx)
{ {

View File

@ -1367,6 +1367,10 @@
; If a script overruns it's event limit, kill the script? ; If a script overruns it's event limit, kill the script?
KillTimedOutScripts = false 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 ; Sets the multiplier for the scripting delays
ScriptDelayFactor = 1.0 ScriptDelayFactor = 1.0