aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
diff options
context:
space:
mode:
authorJustin Clark-Casey (justincc)2013-01-16 00:12:40 +0000
committerJustin Clark-Casey (justincc)2013-01-16 00:12:40 +0000
commit1b5c41c14ad11325be249ea1cce3c65d4d6a89be (patch)
tree987e140c9402c48cc8daf59d2b8af165646cc93a /OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
parentInstead of passing separate engine, part and item components to script APIs, ... (diff)
downloadopensim-SC_OLD-1b5c41c14ad11325be249ea1cce3c65d4d6a89be.zip
opensim-SC_OLD-1b5c41c14ad11325be249ea1cce3c65d4d6a89be.tar.gz
opensim-SC_OLD-1b5c41c14ad11325be249ea1cce3c65d4d6a89be.tar.bz2
opensim-SC_OLD-1b5c41c14ad11325be249ea1cce3c65d4d6a89be.tar.xz
Implement co-operative script termination if termination comes during a script wait event (llSleep(), etc.)
This makes use of EventWaitHandles since various web references indicate that Thread.Interrupt() can also cause runtime instability. If co-op termination is enabled, then termination sets the wait handle instead of waiting for a timeout before possibly aborting the thread. This allows the script to cleanly terminate if it's in a llSleep/LL function delay or the next time it enters such a wait without any timeout period. Co-op termination is not yet testable since checking for termination request within loops that never trigger a wait is not yet implemented.
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs')
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs52
1 files changed, 49 insertions, 3 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index a2ff51b..00048a1 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -200,6 +200,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
200 200
201 public static readonly long MaxMeasurementPeriod = 30 * TimeSpan.TicksPerMinute; 201 public static readonly long MaxMeasurementPeriod = 30 * TimeSpan.TicksPerMinute;
202 202
203 public bool CoopTermination { get; private set; }
204
205 public EventWaitHandle CoopSleepHandle { get; private set; }
206
203 public void ClearQueue() 207 public void ClearQueue()
204 { 208 {
205 m_TimerQueued = false; 209 m_TimerQueued = false;
@@ -233,6 +237,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
233 m_postOnRez = postOnRez; 237 m_postOnRez = postOnRez;
234 m_AttachedAvatar = Part.ParentGroup.AttachedAvatar; 238 m_AttachedAvatar = Part.ParentGroup.AttachedAvatar;
235 m_RegionID = Part.ParentGroup.Scene.RegionInfo.RegionID; 239 m_RegionID = Part.ParentGroup.Scene.RegionInfo.RegionID;
240
241 if (Engine.Config.GetString("ScriptStopStrategy", "abort") == "co-op")
242 {
243 CoopTermination = true;
244 CoopSleepHandle = new AutoResetEvent(false);
245 }
236 } 246 }
237 247
238 /// <summary> 248 /// <summary>
@@ -532,9 +542,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
532 } 542 }
533 543
534 // Wait for the current event to complete. 544 // Wait for the current event to complete.
535 if (!m_InSelfDelete && workItem.Wait(new TimeSpan((long)timeout * 100000))) 545 if (!m_InSelfDelete)
536 { 546 {
537 return true; 547 if (!CoopTermination)
548 {
549 // If we're not co-operative terminating then try and wait for the event to complete before stopping
550 if (workItem.Wait(new TimeSpan((long)timeout * 100000)))
551 return true;
552 }
553 else
554 {
555 m_log.DebugFormat(
556 "[SCRIPT INSTANCE]: Co-operatively stopping script {0} {1} in {2} {3}",
557 ScriptName, ItemID, PrimName, ObjectID);
558
559 // This will terminate the event on next handle check by the script.
560 CoopSleepHandle.Set();
561
562 // For now, we will wait forever since the event should always cleanly terminate once LSL loop
563 // checking is implemented. May want to allow a shorter timeout option later.
564 if (workItem.Wait(TimeSpan.MaxValue))
565 {
566 m_log.DebugFormat(
567 "[SCRIPT INSTANCE]: Co-operatively stopped script {0} {1} in {2} {3}",
568 ScriptName, ItemID, PrimName, ObjectID);
569
570 return true;
571 }
572 }
538 } 573 }
539 574
540 lock (EventQueue) 575 lock (EventQueue)
@@ -547,6 +582,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
547 582
548 // If the event still hasn't stopped and we the stop isn't the result of script or object removal, then 583 // If the event still hasn't stopped and we the stop isn't the result of script or object removal, then
549 // forcibly abort the work item (this aborts the underlying thread). 584 // forcibly abort the work item (this aborts the underlying thread).
585 // Co-operative termination should never reach this point.
550 if (!m_InSelfDelete) 586 if (!m_InSelfDelete)
551 { 587 {
552 m_log.DebugFormat( 588 m_log.DebugFormat(
@@ -786,7 +822,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
786 m_InEvent = false; 822 m_InEvent = false;
787 m_CurrentEvent = String.Empty; 823 m_CurrentEvent = String.Empty;
788 824
789 if ((!(e is TargetInvocationException) || (!(e.InnerException is SelfDeleteException) && !(e.InnerException is ScriptDeleteException))) && !(e is ThreadAbortException)) 825 if ((!(e is TargetInvocationException)
826 || (!(e.InnerException is SelfDeleteException)
827 && !(e.InnerException is ScriptDeleteException)
828 && !(e.InnerException is ScriptCoopStopException)))
829 && !(e is ThreadAbortException))
790 { 830 {
791 try 831 try
792 { 832 {
@@ -834,6 +874,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
834 m_InSelfDelete = true; 874 m_InSelfDelete = true;
835 Part.Inventory.RemoveInventoryItem(ItemID); 875 Part.Inventory.RemoveInventoryItem(ItemID);
836 } 876 }
877 else if ((e is TargetInvocationException) && (e.InnerException is ScriptCoopStopException))
878 {
879 m_log.DebugFormat(
880 "[SCRIPT INSTANCE]: Script {0}.{1} in event {2}, state {3} stopped co-operatively.",
881 PrimName, ScriptName, data.EventName, State);
882 }
837 } 883 }
838 } 884 }
839 } 885 }