From e14c8f59f7205ac010ed13387950647e5023b335 Mon Sep 17 00:00:00 2001 From: Tedd Hansen Date: Fri, 1 Feb 2008 20:45:15 +0000 Subject: Added config options: ScriptThreadPriority to set script thread priority DeactivateScriptOnTimeout to remove script if it is executing too long --- .../Common/ScriptEngineBase/EventQueueManager.cs | 5 ++- .../ScriptEngineBase/EventQueueThreadClass.cs | 43 +++++++++++++++++++++- bin/OpenSim.ini.example | 11 +++++- 3 files changed, 56 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs index 6b2db35..d5826b7 100644 --- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs +++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueManager.cs @@ -82,11 +82,13 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase /// private int numberOfThreads; + /// /// Maximum time one function can use for execution before we perform a thread kill /// private int maxFunctionExecutionTimems; private bool EnforceMaxExecutionTime; + private bool KillScriptOnMaxFunctionExecutionTime; /// @@ -169,7 +171,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase maxFunctionExecutionTimems = m_ScriptEngine.ScriptConfigSource.GetInt("MaxEventExecutionTimeMs", 5000); EnforceMaxExecutionTime = m_ScriptEngine.ScriptConfigSource.GetBoolean("EnforceMaxEventExecutionTime", false); - + KillScriptOnMaxFunctionExecutionTime = m_ScriptEngine.ScriptConfigSource.GetBoolean("DeactivateScriptOnTimeout", false); // Start function max exec time enforcement thread @@ -336,6 +338,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase maxFunctionExecutionTimems) { // We need to kill this thread! + EventQueueThread.KillCurrentScript = KillScriptOnMaxFunctionExecutionTime; AbortThreadClass(EventQueueThread); // Then start another StartNewThreadClass(); diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs index 67cf0e2..57caad5 100644 --- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs +++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs @@ -21,10 +21,12 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase public DateTime LastExecutionStarted; public bool InExecution = false; + public bool KillCurrentScript = false; private EventQueueManager eventQueueManager; public Thread EventQueueThread; private static int ThreadCount = 0; + private ThreadPriority MyThreadPriority; public EventQueueThreadClass(EventQueueManager eqm) { @@ -43,9 +45,36 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase /// private void Start() { + // Later with ScriptServer we might want to ask OS for stuff too, so doing this a bit manually + string pri = eventQueueManager.m_ScriptEngine.ScriptConfigSource.GetString("ScriptThreadPriority", "BelowNormal"); + switch (pri.ToLower()) + { + case "lowest": + MyThreadPriority = ThreadPriority.Lowest; + break; + case "belownormal": + MyThreadPriority = ThreadPriority.BelowNormal; + break; + case "normal": + MyThreadPriority = ThreadPriority.Normal; + break; + case "abovenormal": + MyThreadPriority = ThreadPriority.AboveNormal; + break; + case "highest": + MyThreadPriority = ThreadPriority.Highest; + break; + default: + MyThreadPriority = ThreadPriority.BelowNormal; // Default + eventQueueManager.m_ScriptEngine.Log.Error("ScriptEngineBase", "Unknown priority type \"" + pri + "\" in config file. Defaulting to \"BelowNormal\"."); + break; + } + + EventQueueThread = new Thread(EventQueueThreadLoop); EventQueueThread.IsBackground = true; - EventQueueThread.Priority = ThreadPriority.BelowNormal; + + EventQueueThread.Priority = MyThreadPriority; EventQueueThread.Name = "EventQueueManagerThread_" + ThreadCount; EventQueueThread.Start(); @@ -134,6 +163,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase + ", QIS.functionName: " + QIS.functionName); #endif LastExecutionStarted = DateTime.Now; + KillCurrentScript = false; InExecution = true; eventQueueManager.m_ScriptEngine.m_ScriptManager.ExecuteEvent(QIS.localID, QIS.itemID, QIS.functionName, QIS.llDetectParams, QIS.param); @@ -155,6 +185,9 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase // Send normal text += e.Message.ToString(); } + if (KillCurrentScript) + text += "\r\nScript will be deactivated!"; + try { if (text.Length > 1500) @@ -174,6 +207,14 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase eventQueueManager.m_ScriptEngine.Log.Error("ScriptEngine", "Unable to send text in-world:\r\n" + text); } + finally + { + // So we are done sending message in-world + if (KillCurrentScript) + { + eventQueueManager.m_ScriptEngine.m_ScriptManager.RemoveScript(QIS.localID, QIS.itemID); + } + } } finally { diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index a0ada5c..3169cd0 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -127,13 +127,17 @@ shout_distance = 100 ; Threads are shared across all regions NumberOfScriptThreads=2 +; Script event execution thread priority inside application. +; Valid values: Lowest, BelowNormal, Normal, AboveNormal, Highest +ScriptThreadPriority=BelowNormal + ; Should the script threads be private for each region? ; true: Each region will get dedicated to scripts within that region ; Number of threads will be * ; false: All regions share for all their scripts PrivateRegionThreads=false -; How long MAX should a script be allowed to run? +; How long MAX should a script event be allowed to run (per event execution)? ; Do not set this too low (like 50ms) as there are some time wasted in simply executing a function ; There is also a small speed penalty for every kill that is made MaxEventExecutionTimeMs=5000 @@ -141,6 +145,11 @@ MaxEventExecutionTimeMs=5000 ; Should we enable the max script event execution thread to look for scripts that exceed their timeslice? EnforceMaxEventExecutionTime=true +; Should we stop the script completely when time exceeds? +; This is useful if you have a high and want to deactivate scripts that go wrong +; Note that for example physics engine can slow down the system and make scripts spend more time +DeactivateScriptOnTimeout=false + ; If no scripts have executed in this pass how long should we sleep before checking again ; Impact: ; Too low and you will waste lots of CPU -- cgit v1.1