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.
0.7.3-post-fixes
Justin Clark-Casey (justincc) 2012-03-15 00:06:52 +00:00
parent e17e376b04
commit 9ecbcb787c
2 changed files with 15 additions and 4 deletions

View File

@ -546,7 +546,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
public bool Stop(int timeout) public bool Stop(int timeout)
{ {
// m_log.DebugFormat( // 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; IScriptWorkItem workItem;
@ -575,7 +576,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
} }
// Wait for the current event to complete. // 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; return true;
} }
@ -592,7 +593,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
// forcibly abort the work item (this aborts the underlying thread). // forcibly abort the work item (this aborts the underlying thread).
if (!m_InSelfDelete) 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(); workItem.Abort();
} }
@ -706,6 +709,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
/// <returns></returns> /// <returns></returns>
public object EventProcessor() 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) lock (m_Script)
{ {
// m_log.DebugFormat("[XEngine]: EventProcessor() invoked for {0}.{1}", PrimName, ScriptName); // m_log.DebugFormat("[XEngine]: EventProcessor() invoked for {0}.{1}", PrimName, ScriptName);

View File

@ -1118,7 +1118,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine
} }
instance.ClearQueue(); 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; // bool objectRemoved = false;
lock (m_PrimObjects) lock (m_PrimObjects)