From 12cebb12d5b095fc8d1a2936b9537ad0e0e7dbe7 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 15 Mar 2012 00:06:52 +0000 Subject: [PATCH] Alleviate an issue where calling Thread.Abort() on script WorkItems can fail to release locks, resulting in a crippled simulator. This seems to be a particular problem with ReaderWriterLockSlim, though other locks can be affected as well. It has been seen to happen when llDie() is called in a linkset running more than one script. Alleviation here means supplying a ScriptInstance.Stop() timeout of 1000ms rather than 0ms, to give events a chance to complete. Also, we check the IsRunning status at the top of the ScriptInstance.EventProcessor() so that another event doesn't start in the mean time. Ultimately, a better solution may have to be found since a long-running event would still exceed the timeout and be aborted. --- .../ScriptEngine/Shared/Instance/ScriptInstance.cs | 13 ++++++++++--- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 6 +++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index b84073067c..6a9cd728e9 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -546,7 +546,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance public bool Stop(int timeout) { // m_log.DebugFormat( -// "[SCRIPT INSTANCE]: Stopping script {0} {1} with timeout {2}", ScriptName, ItemID, timeout); +// "[SCRIPT INSTANCE]: Stopping script {0} {1} in {2} {3} with timeout {4} {5} {6}", +// ScriptName, ItemID, PrimName, ObjectID, timeout, m_InSelfDelete, DateTime.Now.Ticks); IScriptWorkItem workItem; @@ -575,7 +576,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance } // Wait for the current event to complete. - if (workItem.Wait(new TimeSpan((long)timeout * 100000))) + if (!m_InSelfDelete && workItem.Wait(new TimeSpan((long)timeout * 100000))) { return true; } @@ -592,7 +593,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance // forcibly abort the work item (this aborts the underlying thread). if (!m_InSelfDelete) { -// m_log.ErrorFormat("[SCRIPT INSTANCE]: Aborting script {0} {1}", ScriptName, ItemID); +// m_log.ErrorFormat( +// "[SCRIPT INSTANCE]: Aborting script {0} {1} in prim {2} {3} {4} {5}", +// ScriptName, ItemID, PrimName, ObjectID, m_InSelfDelete, DateTime.Now.Ticks); workItem.Abort(); } @@ -706,6 +709,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance /// public object EventProcessor() { + // We check here as the thread stopping this instance from running may itself hold the m_Script lock. + if (!Running) + return 0; + lock (m_Script) { // m_log.DebugFormat("[XEngine]: EventProcessor() invoked for {0}.{1}", PrimName, ScriptName); diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index ab41873bcf..44397b7095 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -1118,7 +1118,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine } instance.ClearQueue(); - instance.Stop(0); + + // 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); + // bool objectRemoved = false; lock (m_PrimObjects)