Execution threads are now shared between regions too. Default thread count regardless of number of regions is now 3. This will save you around 33 threads for a normal 3x3 region server.

But, this is totally completely untested. So it probably won't work for another patch or five.
afrisby-rexmerge
Tedd Hansen 2008-02-22 14:09:38 +00:00
parent 3bb0fe098f
commit a43bb10000
3 changed files with 230 additions and 243 deletions

View File

@ -45,7 +45,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
public class EventQueueManager : iScriptEngineFunctionModule public class EventQueueManager : iScriptEngineFunctionModule
{ {
// //
// Class is instanced in "ScriptEngine" and used by "EventManager" also instanced in "ScriptEngine". // Class is instanced in "ScriptEngine" and used by "EventManager" which is also instanced in "ScriptEngine".
// //
// Class purpose is to queue and execute functions that are received by "EventManager": // Class purpose is to queue and execute functions that are received by "EventManager":
// - allowing "EventManager" to release its event thread immediately, thus not interrupting server execution. // - allowing "EventManager" to release its event thread immediately, thus not interrupting server execution.
@ -68,25 +68,25 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
/// List of threads (classes) processing event queue /// List of threads (classes) processing event queue
/// Note that this may or may not be a reference to a static object depending on PrivateRegionThreads config setting. /// Note that this may or may not be a reference to a static object depending on PrivateRegionThreads config setting.
/// </summary> /// </summary>
internal List<EventQueueThreadClass> eventQueueThreads; // Thread pool that we work on internal static List<EventQueueThreadClass> eventQueueThreads; // Thread pool that we work on
/// <summary> /// <summary>
/// Locking access to eventQueueThreads AND staticGlobalEventQueueThreads. /// Locking access to eventQueueThreads AND staticGlobalEventQueueThreads.
/// </summary> /// </summary>
// private object eventQueueThreadsLock = new object(); // private object eventQueueThreadsLock = new object();
// Static objects for referencing the objects above if we don't have private threads: // Static objects for referencing the objects above if we don't have private threads:
internal static List<EventQueueThreadClass> staticEventQueueThreads; // A static reference used if we don't use private threads //internal static List<EventQueueThreadClass> staticEventQueueThreads; // A static reference used if we don't use private threads
// internal static object staticEventQueueThreadsLock; // Statick lock object reference for same reason // internal static object staticEventQueueThreadsLock; // Statick lock object reference for same reason
/// <summary> /// <summary>
/// Global static list of all threads (classes) processing event queue -- used by max enforcment thread /// Global static list of all threads (classes) processing event queue -- used by max enforcment thread
/// </summary> /// </summary>
private List<EventQueueThreadClass> staticGlobalEventQueueThreads = new List<EventQueueThreadClass>(); //private List<EventQueueThreadClass> staticGlobalEventQueueThreads = new List<EventQueueThreadClass>();
/// <summary> /// <summary>
/// Used internally to specify how many threads should exit gracefully /// Used internally to specify how many threads should exit gracefully
/// </summary> /// </summary>
public int ThreadsToExit; public static int ThreadsToExit;
public object ThreadsToExitLock = new object(); public static object ThreadsToExitLock = new object();
//public object queueLock = new object(); // Mutex lock object //public object queueLock = new object(); // Mutex lock object
@ -94,14 +94,14 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
/// <summary> /// <summary>
/// How many threads to process queue with /// How many threads to process queue with
/// </summary> /// </summary>
internal int numberOfThreads; internal static int numberOfThreads;
internal static int EventExecutionMaxQueueSize; internal static int EventExecutionMaxQueueSize;
/// <summary> /// <summary>
/// Maximum time one function can use for execution before we perform a thread kill. /// Maximum time one function can use for execution before we perform a thread kill.
/// </summary> /// </summary>
private int maxFunctionExecutionTimems private static int maxFunctionExecutionTimems
{ {
get { return (int)(maxFunctionExecutionTimens / 10000); } get { return (int)(maxFunctionExecutionTimens / 10000); }
set { maxFunctionExecutionTimens = value * 10000; } set { maxFunctionExecutionTimens = value * 10000; }
@ -111,15 +111,15 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
/// Contains nanoseconds version of maxFunctionExecutionTimems so that it matches time calculations better (performance reasons). /// Contains nanoseconds version of maxFunctionExecutionTimems so that it matches time calculations better (performance reasons).
/// WARNING! ONLY UPDATE maxFunctionExecutionTimems, NEVER THIS DIRECTLY. /// WARNING! ONLY UPDATE maxFunctionExecutionTimems, NEVER THIS DIRECTLY.
/// </summary> /// </summary>
public long maxFunctionExecutionTimens; public static long maxFunctionExecutionTimens;
/// <summary> /// <summary>
/// Enforce max execution time /// Enforce max execution time
/// </summary> /// </summary>
public bool EnforceMaxExecutionTime; public static bool EnforceMaxExecutionTime;
/// <summary> /// <summary>
/// Kill script (unload) when it exceeds execution time /// Kill script (unload) when it exceeds execution time
/// </summary> /// </summary>
private bool KillScriptOnMaxFunctionExecutionTime; private static bool KillScriptOnMaxFunctionExecutionTime;
/// <summary> /// <summary>
/// List of localID locks for mutex processing of script events /// List of localID locks for mutex processing of script events
@ -172,33 +172,8 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
{ {
m_ScriptEngine = _ScriptEngine; m_ScriptEngine = _ScriptEngine;
// TODO: We need to move from single EventQueueManager to list of it in to share threads eventQueueThreads = new List<EventQueueThreadClass>();
bool PrivateRegionThreads = true; // m_ScriptEngine.ScriptConfigSource.GetBoolean("PrivateRegionThreads", false);
// Create thread pool list and lock object
// Determine from config if threads should be dedicated to regions or shared
if (PrivateRegionThreads)
{
// PRIVATE THREAD POOL PER REGION
eventQueueThreads = new List<EventQueueThreadClass>();
// eventQueueThreadsLock = new object();
}
else
{
// SHARED THREAD POOL
// Crate the static objects
if (staticEventQueueThreads == null)
staticEventQueueThreads = new List<EventQueueThreadClass>();
// if (staticEventQueueThreadsLock == null)
// staticEventQueueThreadsLock = new object();
// Now reference our locals to them
eventQueueThreads = staticEventQueueThreads;
//eventQueueThreadsLock = staticEventQueueThreadsLock;
}
ReadConfig(); ReadConfig();
} }
public void ReadConfig() public void ReadConfig()
@ -230,18 +205,18 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
private void Stop() private void Stop()
{ {
if (eventQueueThreads != null && eventQueueThreads != null) if (eventQueueThreads != null)
{ {
// Kill worker threads // Kill worker threads
//lock (eventQueueThreads) lock (eventQueueThreads)
//{ {
foreach (EventQueueThreadClass EventQueueThread in new ArrayList(eventQueueThreads)) foreach (EventQueueThreadClass EventQueueThread in new ArrayList(eventQueueThreads))
{ {
AbortThreadClass(EventQueueThread); AbortThreadClass(EventQueueThread);
} }
//eventQueueThreads.Clear(); //eventQueueThreads.Clear();
//staticGlobalEventQueueThreads.Clear(); //staticGlobalEventQueueThreads.Clear();
//} }
} }
// Remove all entries from our event queue // Remove all entries from our event queue
@ -256,9 +231,8 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
#region " Start / stop script execution threads (ThreadClasses) " #region " Start / stop script execution threads (ThreadClasses) "
private void StartNewThreadClass() private void StartNewThreadClass()
{ {
EventQueueThreadClass eqtc = new EventQueueThreadClass(this); EventQueueThreadClass eqtc = new EventQueueThreadClass();
eventQueueThreads.Add(eqtc); eventQueueThreads.Add(eqtc);
staticGlobalEventQueueThreads.Add(eqtc);
m_ScriptEngine.Log.Debug("[" + m_ScriptEngine.ScriptEngineName + "]: Started new script execution thread. Current thread count: " + eventQueueThreads.Count); m_ScriptEngine.Log.Debug("[" + m_ScriptEngine.ScriptEngineName + "]: Started new script execution thread. Current thread count: " + eventQueueThreads.Count);
} }
@ -266,8 +240,6 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
{ {
if (eventQueueThreads.Contains(threadClass)) if (eventQueueThreads.Contains(threadClass))
eventQueueThreads.Remove(threadClass); eventQueueThreads.Remove(threadClass);
if (staticGlobalEventQueueThreads.Contains(threadClass))
staticGlobalEventQueueThreads.Remove(threadClass);
try try
{ {
@ -426,7 +398,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
// Iterate through all ScriptThreadClasses and check how long their current function has been executing // Iterate through all ScriptThreadClasses and check how long their current function has been executing
lock (eventQueueThreads) lock (eventQueueThreads)
{ {
foreach (EventQueueThreadClass EventQueueThread in staticGlobalEventQueueThreads) foreach (EventQueueThreadClass EventQueueThread in eventQueueThreads)
{ {
// Is thread currently executing anything? // Is thread currently executing anything?
if (EventQueueThread.InExecution) if (EventQueueThread.InExecution)

View File

@ -40,27 +40,27 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
/// <summary> /// <summary>
/// Because every thread needs some data set for it (time started to execute current function), it will do its work within a class /// Because every thread needs some data set for it (time started to execute current function), it will do its work within a class
/// </summary> /// </summary>
public class EventQueueThreadClass: iScriptEngineFunctionModule public class EventQueueThreadClass : iScriptEngineFunctionModule
{ {
/// <summary> /// <summary>
/// How many ms to sleep if queue is empty /// How many ms to sleep if queue is empty
/// </summary> /// </summary>
private int nothingToDoSleepms;// = 50; private static int nothingToDoSleepms;// = 50;
private ThreadPriority MyThreadPriority; private static ThreadPriority MyThreadPriority;
public long LastExecutionStarted; public long LastExecutionStarted;
public bool InExecution = false; public bool InExecution = false;
public bool KillCurrentScript = false; public bool KillCurrentScript = false;
private EventQueueManager eventQueueManager; //private EventQueueManager eventQueueManager;
public Thread EventQueueThread; public Thread EventQueueThread;
private static int ThreadCount = 0; private static int ThreadCount = 0;
private string ScriptEngineName = "ScriptEngine.Common"; private string ScriptEngineName = "ScriptEngine.Common";
public EventQueueThreadClass(EventQueueManager eqm) public EventQueueThreadClass()//EventQueueManager eqm
{ {
eventQueueManager = eqm; //eventQueueManager = eqm;
ReadConfig(); ReadConfig();
Start(); Start();
} }
@ -72,32 +72,36 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
public void ReadConfig() public void ReadConfig()
{ {
ScriptEngineName = eventQueueManager.m_ScriptEngine.ScriptEngineName; foreach (ScriptEngine m_ScriptEngine in ScriptEngine.ScriptEngines)
nothingToDoSleepms = eventQueueManager.m_ScriptEngine.ScriptConfigSource.GetInt("SleepTimeIfNoScriptExecutionMs", 50);
// 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": ScriptEngineName = m_ScriptEngine.ScriptEngineName;
MyThreadPriority = ThreadPriority.Lowest; nothingToDoSleepms = m_ScriptEngine.ScriptConfigSource.GetInt("SleepTimeIfNoScriptExecutionMs", 50);
break;
case "belownormal": // Later with ScriptServer we might want to ask OS for stuff too, so doing this a bit manually
MyThreadPriority = ThreadPriority.BelowNormal; string pri = m_ScriptEngine.ScriptConfigSource.GetString("ScriptThreadPriority", "BelowNormal");
break; switch (pri.ToLower())
case "normal": {
MyThreadPriority = ThreadPriority.Normal; case "lowest":
break; MyThreadPriority = ThreadPriority.Lowest;
case "abovenormal": break;
MyThreadPriority = ThreadPriority.AboveNormal; case "belownormal":
break; MyThreadPriority = ThreadPriority.BelowNormal;
case "highest": break;
MyThreadPriority = ThreadPriority.Highest; case "normal":
break; MyThreadPriority = ThreadPriority.Normal;
default: break;
MyThreadPriority = ThreadPriority.BelowNormal; // Default case "abovenormal":
eventQueueManager.m_ScriptEngine.Log.Error("[ScriptEngineBase]: Unknown priority type \"" + pri + "\" in config file. Defaulting to \"BelowNormal\"."); MyThreadPriority = ThreadPriority.AboveNormal;
break; break;
case "highest":
MyThreadPriority = ThreadPriority.Highest;
break;
default:
MyThreadPriority = ThreadPriority.BelowNormal; // Default
m_ScriptEngine.Log.Error("[ScriptEngineBase]: Unknown priority type \"" + pri +
"\" in config file. Defaulting to \"BelowNormal\".");
break;
}
} }
// Now set that priority // Now set that priority
@ -113,7 +117,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
{ {
EventQueueThread = new Thread(EventQueueThreadLoop); EventQueueThread = new Thread(EventQueueThreadLoop);
EventQueueThread.IsBackground = true; EventQueueThread.IsBackground = true;
EventQueueThread.Priority = MyThreadPriority; EventQueueThread.Priority = MyThreadPriority;
EventQueueThread.Name = "EventQueueManagerThread_" + ThreadCount; EventQueueThread.Name = "EventQueueManagerThread_" + ThreadCount;
EventQueueThread.Start(); EventQueueThread.Start();
@ -127,8 +131,8 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
public void Stop() public void Stop()
{ {
PleaseShutdown = true; // Set shutdown flag //PleaseShutdown = true; // Set shutdown flag
Thread.Sleep(100); // Wait a bit //Thread.Sleep(100); // Wait a bit
if (EventQueueThread != null && EventQueueThread.IsAlive == true) if (EventQueueThread != null && EventQueueThread.IsAlive == true)
{ {
try try
@ -143,6 +147,8 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
} }
} }
private EventQueueManager.QueueItemStruct BlankQIS = new EventQueueManager.QueueItemStruct();
private ScriptEngine lastScriptEngine;
/// <summary> /// <summary>
/// Queue processing thread loop /// Queue processing thread loop
/// </summary> /// </summary>
@ -151,171 +157,24 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
//myScriptEngine.Log.Info("[" + ScriptEngineName + "]: EventQueueManager Worker thread spawned"); //myScriptEngine.Log.Info("[" + ScriptEngineName + "]: EventQueueManager Worker thread spawned");
try try
{ {
while (true) while (true)
{ {
try try
{ {
EventQueueManager.QueueItemStruct BlankQIS = new EventQueueManager.QueueItemStruct();
while (true) while (true)
{ {
// Every now and then check if we should shut down DoProcessQueue();
if (PleaseShutdown || eventQueueManager.ThreadsToExit > 0)
{
// Someone should shut down, lets get exclusive lock
lock (eventQueueManager.ThreadsToExitLock)
{
// Lets re-check in case someone grabbed it
if (eventQueueManager.ThreadsToExit > 0)
{
// Its crowded here so we'll shut down
eventQueueManager.ThreadsToExit--;
Stop();
return;
}
else
{
// We have been asked to shut down
Stop();
return;
}
}
}
//try
// {
EventQueueManager.QueueItemStruct QIS = BlankQIS;
bool GotItem = false;
if (PleaseShutdown)
return;
if (eventQueueManager.eventQueue.Count == 0)
{
// Nothing to do? Sleep a bit waiting for something to do
Thread.Sleep(nothingToDoSleepms);
}
else
{
// Something in queue, process
//myScriptEngine.Log.Info("[" + ScriptEngineName + "]: Processing event for localID: " + QIS.localID + ", itemID: " + QIS.itemID + ", FunctionName: " + QIS.FunctionName);
// OBJECT BASED LOCK - TWO THREADS WORKING ON SAME OBJECT IS NOT GOOD
lock (eventQueueManager.eventQueue)
{
GotItem = false;
for (int qc = 0; qc < eventQueueManager.eventQueue.Count; qc++)
{
// Get queue item
QIS = eventQueueManager.eventQueue.Dequeue();
// Check if object is being processed by someone else
if (eventQueueManager.TryLock(QIS.localID) == false)
{
// Object is already being processed, requeue it
eventQueueManager.eventQueue.Enqueue(QIS);
}
else
{
// We have lock on an object and can process it
GotItem = true;
break;
}
}
}
if (GotItem == true)
{
// Execute function
try
{
///cfk 2-7-08 dont need this right now and the default Linux build has DEBUG defined
#if DEBUG
//eventQueueManager.m_ScriptEngine.Log.Debug("[" + ScriptEngineName + "]: " +
// "Executing event:\r\n"
// + "QIS.localID: " + QIS.localID
// + ", QIS.itemID: " + QIS.itemID
// + ", QIS.functionName: " +
// QIS.functionName);
#endif
LastExecutionStarted = DateTime.Now.Ticks;
KillCurrentScript = false;
InExecution = true;
eventQueueManager.m_ScriptEngine.m_ScriptManager.ExecuteEvent(QIS.localID,
QIS.itemID,
QIS.functionName,
QIS.llDetectParams,
QIS.param);
InExecution = false;
}
catch (Exception e)
{
InExecution = false;
// DISPLAY ERROR INWORLD
string text = "Error executing script function \"" + QIS.functionName +
"\":\r\n";
if (e.InnerException != null)
{
// Send inner exception
text += e.InnerException.Message.ToString();
}
else
{
text += "\r\n";
// Send normal
text += e.Message.ToString();
}
if (KillCurrentScript)
text += "\r\nScript will be deactivated!";
try
{
if (text.Length > 1500)
text = text.Substring(0, 1500);
IScriptHost m_host =
eventQueueManager.m_ScriptEngine.World.GetSceneObjectPart(QIS.localID);
//if (m_host != null)
//{
eventQueueManager.m_ScriptEngine.World.SimChat(Helpers.StringToField(text),
ChatTypeEnum.Say, 0,
m_host.AbsolutePosition,
m_host.Name, m_host.UUID);
}
catch
{
//}
//else
//{
// T oconsole
eventQueueManager.m_ScriptEngine.Log.Error("[" + ScriptEngineName + "]: " +
"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.StopScript(
QIS.localID, QIS.itemID);
}
}
}
finally
{
InExecution = false;
eventQueueManager.ReleaseLock(QIS.localID);
}
}
}
} }
} }
catch (ThreadAbortException tae) catch (ThreadAbortException tae)
{ {
eventQueueManager.m_ScriptEngine.Log.Info("[" + ScriptEngineName + "]: ThreadAbortException while executing function."); if (lastScriptEngine != null)
lastScriptEngine.Log.Info("[" + ScriptEngineName + "]: ThreadAbortException while executing function.");
} }
catch (Exception e) catch (Exception e)
{ {
eventQueueManager.m_ScriptEngine.Log.Error("[" + ScriptEngineName + "]: Exception in EventQueueThreadLoop: " + e.ToString()); if (lastScriptEngine != null)
lastScriptEngine.Log.Error("[" + ScriptEngineName + "]: Exception in EventQueueThreadLoop: " + e.ToString());
} }
} }
} }
@ -325,14 +184,171 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
} }
} }
/// <summary> public void DoProcessQueue()
/// If set to true then threads and stuff should try to make a graceful exit
/// </summary>
public bool PleaseShutdown
{ {
get { return _PleaseShutdown; } foreach (ScriptEngine m_ScriptEngine in ScriptEngine.ScriptEngines)
set { _PleaseShutdown = value; } {
lastScriptEngine = m_ScriptEngine;
// Every now and then check if we should shut down
//if (PleaseShutdown || EventQueueManager.ThreadsToExit > 0)
//{
// // Someone should shut down, lets get exclusive lock
// lock (EventQueueManager.ThreadsToExitLock)
// {
// // Lets re-check in case someone grabbed it
// if (EventQueueManager.ThreadsToExit > 0)
// {
// // Its crowded here so we'll shut down
// EventQueueManager.ThreadsToExit--;
// Stop();
// return;
// }
// else
// {
// // We have been asked to shut down
// Stop();
// return;
// }
// }
//}
//try
// {
EventQueueManager.QueueItemStruct QIS = BlankQIS;
bool GotItem = false;
//if (PleaseShutdown)
// return;
if (m_ScriptEngine.m_EventQueueManager.eventQueue.Count == 0)
{
// Nothing to do? Sleep a bit waiting for something to do
Thread.Sleep(nothingToDoSleepms);
}
else
{
// Something in queue, process
//myScriptEngine.Log.Info("[" + ScriptEngineName + "]: Processing event for localID: " + QIS.localID + ", itemID: " + QIS.itemID + ", FunctionName: " + QIS.FunctionName);
// OBJECT BASED LOCK - TWO THREADS WORKING ON SAME OBJECT IS NOT GOOD
lock (m_ScriptEngine.m_EventQueueManager.eventQueue)
{
GotItem = false;
for (int qc = 0; qc < m_ScriptEngine.m_EventQueueManager.eventQueue.Count; qc++)
{
// Get queue item
QIS = m_ScriptEngine.m_EventQueueManager.eventQueue.Dequeue();
// Check if object is being processed by someone else
if (m_ScriptEngine.m_EventQueueManager.TryLock(QIS.localID) == false)
{
// Object is already being processed, requeue it
m_ScriptEngine.m_EventQueueManager.eventQueue.Enqueue(QIS);
}
else
{
// We have lock on an object and can process it
GotItem = true;
break;
}
}
}
if (GotItem == true)
{
// Execute function
try
{
///cfk 2-7-08 dont need this right now and the default Linux build has DEBUG defined
#if DEBUG
//eventQueueManager.m_ScriptEngine.Log.Debug("[" + ScriptEngineName + "]: " +
// "Executing event:\r\n"
// + "QIS.localID: " + QIS.localID
// + ", QIS.itemID: " + QIS.itemID
// + ", QIS.functionName: " +
// QIS.functionName);
#endif
LastExecutionStarted = DateTime.Now.Ticks;
KillCurrentScript = false;
InExecution = true;
m_ScriptEngine.m_ScriptManager.ExecuteEvent(QIS.localID,
QIS.itemID,
QIS.functionName,
QIS.llDetectParams,
QIS.param);
InExecution = false;
}
catch (Exception e)
{
InExecution = false;
// DISPLAY ERROR INWORLD
string text = "Error executing script function \"" + QIS.functionName +
"\":\r\n";
if (e.InnerException != null)
{
// Send inner exception
text += e.InnerException.Message.ToString();
}
else
{
text += "\r\n";
// Send normal
text += e.Message.ToString();
}
if (KillCurrentScript)
text += "\r\nScript will be deactivated!";
try
{
if (text.Length > 1500)
text = text.Substring(0, 1500);
IScriptHost m_host =
m_ScriptEngine.World.GetSceneObjectPart(QIS.localID);
//if (m_host != null)
//{
m_ScriptEngine.World.SimChat(Helpers.StringToField(text),
ChatTypeEnum.Say, 0,
m_host.AbsolutePosition,
m_host.Name, m_host.UUID);
}
catch
{
//}
//else
//{
// T oconsole
m_ScriptEngine.m_EventQueueManager.m_ScriptEngine.Log.Error("[" + ScriptEngineName + "]: " +
"Unable to send text in-world:\r\n" +
text);
}
finally
{
// So we are done sending message in-world
if (KillCurrentScript)
{
m_ScriptEngine.m_EventQueueManager.m_ScriptEngine.m_ScriptManager.StopScript(
QIS.localID, QIS.itemID);
}
}
}
finally
{
InExecution = false;
m_ScriptEngine.m_EventQueueManager.ReleaseLock(QIS.localID);
}
}
}
}
} }
private bool _PleaseShutdown = false;
///// <summary>
///// If set to true then threads and stuff should try to make a graceful exit
///// </summary>
//public bool PleaseShutdown
//{
// get { return _PleaseShutdown; }
// set { _PleaseShutdown = value; }
//}
//private bool _PleaseShutdown = false;
} }
} }

View File

@ -156,12 +156,11 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
m_ScriptEngine.m_EventQueueManager.AdjustNumberOfScriptThreads(); m_ScriptEngine.m_EventQueueManager.AdjustNumberOfScriptThreads();
// Check if any script has exceeded its max execution time // Check if any script has exceeded its max execution time
if (m_ScriptEngine.m_EventQueueManager != null && if (EventQueueManager.EnforceMaxExecutionTime)
m_ScriptEngine.m_EventQueueManager.EnforceMaxExecutionTime)
{ {
// We are enforcing execution time // We are enforcing execution time
if (DateTime.Now.Ticks - Last_maxFunctionExecutionTimens > if (DateTime.Now.Ticks - Last_maxFunctionExecutionTimens >
m_ScriptEngine.m_EventQueueManager.maxFunctionExecutionTimens) EventQueueManager.maxFunctionExecutionTimens)
{ {
// Its time to check again // Its time to check again
m_ScriptEngine.m_EventQueueManager.CheckScriptMaxExecTime(); // Do check m_ScriptEngine.m_EventQueueManager.CheckScriptMaxExecTime(); // Do check