From f06a6573bb94d1a61ddabd1289d0ea541f7788c1 Mon Sep 17 00:00:00 2001
From: Tedd Hansen
Date: Fri, 22 Feb 2008 22:24:12 +0000
Subject: One more: Async LSL command thread is also shared now.

---
 .../ScriptEngineBase/AsyncLSLCommandManager.cs     |  81 +++--
 .../ScriptEngineBase/EventQueueThreadClass.cs      | 328 +++++++++++----------
 .../Common/ScriptEngineBase/MaintenanceThread.cs   |  86 +++---
 .../Common/ScriptEngineBase/ScriptEngine.cs        |  28 +-
 bin/OpenSim.ini.example                            |  10 +-
 5 files changed, 279 insertions(+), 254 deletions(-)

diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncLSLCommandManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncLSLCommandManager.cs
index fbdfff8..556593d 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncLSLCommandManager.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/AsyncLSLCommandManager.cs
@@ -41,28 +41,36 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
     /// </summary>
     public class AsyncLSLCommandManager : iScriptEngineFunctionModule
     {
-        private Thread cmdHandlerThread;
+        private static Thread cmdHandlerThread;
         private int cmdHandlerThreadCycleSleepms;
 
         private ScriptEngine m_ScriptEngine;
 
-        public AsyncLSLCommandManager(ScriptEngine _ScriptEngine)
+        public AsyncLSLCommandManager()
         {
-            m_ScriptEngine = _ScriptEngine;
+            //m_ScriptEngine = _ScriptEngine;
             ReadConfig();
 
-            // Start the thread that will be doing the work
-            cmdHandlerThread = new Thread(CmdHandlerThreadLoop);
-            cmdHandlerThread.Name = "CmdHandlerThread";
-            cmdHandlerThread.Priority = ThreadPriority.BelowNormal;
-            cmdHandlerThread.IsBackground = true;
-            cmdHandlerThread.Start();
-            OpenSim.Framework.ThreadTracker.Add(cmdHandlerThread);
+            StartThread();
+        }
+
+        private void StartThread()
+        {
+            if (cmdHandlerThread == null)
+            {
+                // Start the thread that will be doing the work
+                cmdHandlerThread = new Thread(CmdHandlerThreadLoop);
+                cmdHandlerThread.Name = "AsyncLSLCmdHandlerThread";
+                cmdHandlerThread.Priority = ThreadPriority.BelowNormal;
+                cmdHandlerThread.IsBackground = true;
+                cmdHandlerThread.Start();
+                OpenSim.Framework.ThreadTracker.Add(cmdHandlerThread);
+            }
         }
 
         public void ReadConfig()
         {
-            cmdHandlerThreadCycleSleepms = m_ScriptEngine.ScriptConfigSource.GetInt("AsyncLLCommandLoopms", 50);
+            cmdHandlerThreadCycleSleepms = m_ScriptEngine.ScriptConfigSource.GetInt("AsyncLLCommandLoopms", 100);
         }
 
         ~AsyncLSLCommandManager()
@@ -88,29 +96,46 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
         {
             while (true)
             {
-                // Check timers
-                CheckTimerEvents();
-                Thread.Sleep(25);
-                // Check HttpRequests
-                CheckHttpRequests();
-                Thread.Sleep(25);
-                // Check XMLRPCRequests
-                CheckXMLRPCRequests();
-                Thread.Sleep(25);
-                // Check Listeners
-                CheckListeners();
-                Thread.Sleep(25);
-
-                // Sleep before next cycle
-                //Thread.Sleep(cmdHandlerThreadCycleSleepms);
+                try
+                {
+                    while (true)
+                    {
+                        Thread.Sleep(cmdHandlerThreadCycleSleepms);
+                        lock (ScriptEngine.ScriptEngines)
+                        {
+                            foreach (ScriptEngine se in ScriptEngine.ScriptEngines) 
+                            {
+                                m_ScriptEngine = se;
+                                m_ScriptEngine.m_ASYNCLSLCommandManager.DoOneCmdHandlerPass();
+                            }
+                        }
+                        // Sleep before next cycle
+                        //Thread.Sleep(cmdHandlerThreadCycleSleepms);
+                    }
+                }
+                catch
+                {
+                }
             }
         }
 
+        internal void DoOneCmdHandlerPass()
+        {
+            // Check timers
+            CheckTimerEvents();
+            // Check HttpRequests
+            CheckHttpRequests();
+            // Check XMLRPCRequests
+            CheckXMLRPCRequests();
+            // Check Listeners
+            CheckListeners();
+        }
+
         /// <summary>
         /// Remove a specific script (and all its pending commands)
         /// </summary>
-        /// <param name="m_localID"></param>
-        /// <param name="m_itemID"></param>
+        /// <param name="localID"></param>
+        /// <param name="itemID"></param>
         public void RemoveScript(uint localID, LLUUID itemID)
         {
             // Remove a specific script
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs
index c0edcc4..a70e93b 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/EventQueueThreadClass.cs
@@ -73,38 +73,40 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
 
         public void ReadConfig()
         {
-            foreach (ScriptEngine m_ScriptEngine in new ArrayList(ScriptEngine.ScriptEngines))
-            {
-                ScriptEngineName = m_ScriptEngine.ScriptEngineName;
-                nothingToDoSleepms = 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 = m_ScriptEngine.ScriptConfigSource.GetString("ScriptThreadPriority", "BelowNormal");
-                switch (pri.ToLower())
+            //lock (ScriptEngine.ScriptEngines)
+            //{
+                foreach (ScriptEngine m_ScriptEngine in new ArrayList(ScriptEngine.ScriptEngines))
                 {
-                    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
-                        m_ScriptEngine.Log.Error("[ScriptEngineBase]: Unknown priority type \"" + pri +
-                                                 "\" in config file. Defaulting to \"BelowNormal\".");
-                        break;
-                }
-            }
+                    ScriptEngineName = m_ScriptEngine.ScriptEngineName;
+                    nothingToDoSleepms = 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 = 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
+                            m_ScriptEngine.Log.Error("[ScriptEngineBase]: Unknown priority type \"" + pri +
+                                                     "\" in config file. Defaulting to \"BelowNormal\".");
+                            break;
+                    }
+                }
+            //}
             // Now set that priority
             if (EventQueueThread != null)
                 if (EventQueueThread.IsAlive)
@@ -187,159 +189,163 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
 
         public void DoProcessQueue()
         {
-            foreach (ScriptEngine m_ScriptEngine in new ArrayList(ScriptEngine.ScriptEngines))
-            {
-                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;
-                //        }
-                //    }
-                //}
+            //lock (ScriptEngine.ScriptEngines)
+            //{
+                foreach (ScriptEngine m_ScriptEngine in new ArrayList(ScriptEngine.ScriptEngines))
+                {
+                    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;
+                    //try
+                    //  {
+                    EventQueueManager.QueueItemStruct QIS = BlankQIS;
+                    bool GotItem = false;
 
-                //if (PleaseShutdown)
-                //    return;
+                    //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)
+                    if (m_ScriptEngine.m_EventQueueManager.eventQueue.Count == 0)
                     {
-                        GotItem = false;
-                        for (int qc = 0; qc < m_ScriptEngine.m_EventQueueManager.eventQueue.Count; qc++)
-                        {
-                            // Get queue item
-                            QIS = m_ScriptEngine.m_EventQueueManager.eventQueue.Dequeue();
+                        // 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);
 
-                            // 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
+                        // 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++)
                             {
-                                // We have lock on an object and can process it
-                                GotItem = true;
-                                break;
+                                // 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
+                        if (GotItem == true)
                         {
-                            ///cfk 2-7-08 dont need this right now and the default Linux build has DEBUG defined
+                            // 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);
+                                //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();
+                                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;
                             }
-                            else
+                            catch (Exception e)
                             {
-                                text += "\r\n";
-                                // Send normal
-                                text += e.Message.ToString();
-                            }
-                            if (KillCurrentScript)
-                                text += "\r\nScript will be deactivated!";
+                                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);
+                                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
                             {
-                                // So we are done sending message in-world
-                                if (KillCurrentScript)
-                                {
-                                    m_ScriptEngine.m_EventQueueManager.m_ScriptEngine.m_ScriptManager.StopScript(
-                                        QIS.localID, QIS.itemID);
-                                }
+                                InExecution = false;
+                                m_ScriptEngine.m_EventQueueManager.ReleaseLock(QIS.localID);
                             }
                         }
-                        finally
-                        {
-                            InExecution = false;
-                            m_ScriptEngine.m_EventQueueManager.ReleaseLock(QIS.localID);
-                        }
                     }
                 }
-            }
+           // }
         }
 
         ///// <summary>
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/MaintenanceThread.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/MaintenanceThread.cs
index e0ec27f..eb57a9e 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/MaintenanceThread.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/MaintenanceThread.cs
@@ -63,13 +63,18 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
         public void ReadConfig()
         {
             // Bad hack, but we need a m_ScriptEngine :)
-            foreach (ScriptEngine m_ScriptEngine in ScriptEngine.ScriptEngines)
+            lock (ScriptEngine.ScriptEngines)
             {
-                MaintenanceLoopms = m_ScriptEngine.ScriptConfigSource.GetInt("MaintenanceLoopms", 50);
-                MaintenanceLoopTicks_ScriptLoadUnload = m_ScriptEngine.ScriptConfigSource.GetInt("MaintenanceLoopTicks_ScriptLoadUnload", 1);
-                MaintenanceLoopTicks_Other = m_ScriptEngine.ScriptConfigSource.GetInt("MaintenanceLoopTicks_Other", 10);
+                foreach (ScriptEngine m_ScriptEngine in ScriptEngine.ScriptEngines)
+                {
+                    MaintenanceLoopms = m_ScriptEngine.ScriptConfigSource.GetInt("MaintenanceLoopms", 50);
+                    MaintenanceLoopTicks_ScriptLoadUnload =
+                        m_ScriptEngine.ScriptConfigSource.GetInt("MaintenanceLoopTicks_ScriptLoadUnload", 1);
+                    MaintenanceLoopTicks_Other =
+                        m_ScriptEngine.ScriptConfigSource.GetInt("MaintenanceLoopTicks_Other", 10);
 
-                return;
+                    return;
+                }
             }
         }
 
@@ -159,52 +164,53 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
                         MaintenanceLoopTicks_Other_Count++;
 
 
-                        foreach (ScriptEngine m_ScriptEngine in new ArrayList(ScriptEngine.ScriptEngines))
+                        lock (ScriptEngine.ScriptEngines)
                         {
-                            lastScriptEngine = m_ScriptEngine;
-                            // Re-reading config every x seconds
-                            if (MaintenanceLoopTicks_Other_Count >= MaintenanceLoopTicks_Other)
+                            foreach (ScriptEngine m_ScriptEngine in ScriptEngine.ScriptEngines)
                             {
-                                MaintenanceLoopTicks_Other_ResetCount = true;
-                                if (m_ScriptEngine.RefreshConfigFilens > 0)
+                                lastScriptEngine = m_ScriptEngine;
+                                // Re-reading config every x seconds
+                                if (MaintenanceLoopTicks_Other_Count >= MaintenanceLoopTicks_Other)
                                 {
-
-                                    // Check if its time to re-read config
-                                    if (DateTime.Now.Ticks - Last_ReReadConfigFilens >
-                                        m_ScriptEngine.RefreshConfigFilens)
+                                    MaintenanceLoopTicks_Other_ResetCount = true;
+                                    if (m_ScriptEngine.RefreshConfigFilens > 0)
                                     {
-                                        //Console.WriteLine("Time passed: " + (DateTime.Now.Ticks - Last_ReReadConfigFilens) + ">" + m_ScriptEngine.RefreshConfigFilens );
-                                        // Its time to re-read config file
-                                        m_ScriptEngine.ReadConfig();
-                                        Last_ReReadConfigFilens = DateTime.Now.Ticks; // Reset time
-                                    }
+                                        // Check if its time to re-read config
+                                        if (DateTime.Now.Ticks - Last_ReReadConfigFilens >
+                                            m_ScriptEngine.RefreshConfigFilens)
+                                        {
+                                            //Console.WriteLine("Time passed: " + (DateTime.Now.Ticks - Last_ReReadConfigFilens) + ">" + m_ScriptEngine.RefreshConfigFilens );
+                                            // Its time to re-read config file
+                                            m_ScriptEngine.ReadConfig();
+                                            Last_ReReadConfigFilens = DateTime.Now.Ticks; // Reset time
+                                        }
 
 
-                                    // Adjust number of running script threads if not correct
-                                    if (m_ScriptEngine.m_EventQueueManager != null)
-                                        m_ScriptEngine.m_EventQueueManager.AdjustNumberOfScriptThreads();
+                                        // Adjust number of running script threads if not correct
+                                        if (m_ScriptEngine.m_EventQueueManager != null)
+                                            m_ScriptEngine.m_EventQueueManager.AdjustNumberOfScriptThreads();
 
-                                    // Check if any script has exceeded its max execution time
-                                    if (EventQueueManager.EnforceMaxExecutionTime)
-                                    {
-                                        // We are enforcing execution time
-                                        if (DateTime.Now.Ticks - Last_maxFunctionExecutionTimens >
-                                            EventQueueManager.maxFunctionExecutionTimens)
+                                        // Check if any script has exceeded its max execution time
+                                        if (EventQueueManager.EnforceMaxExecutionTime)
                                         {
-                                            // Its time to check again
-                                            m_ScriptEngine.m_EventQueueManager.CheckScriptMaxExecTime(); // Do check
-                                            Last_maxFunctionExecutionTimens = DateTime.Now.Ticks; // Reset time
+                                            // We are enforcing execution time
+                                            if (DateTime.Now.Ticks - Last_maxFunctionExecutionTimens >
+                                                EventQueueManager.maxFunctionExecutionTimens)
+                                            {
+                                                // Its time to check again
+                                                m_ScriptEngine.m_EventQueueManager.CheckScriptMaxExecTime(); // Do check
+                                                Last_maxFunctionExecutionTimens = DateTime.Now.Ticks; // Reset time
+                                            }
                                         }
                                     }
                                 }
-
-                            }
-                            if (MaintenanceLoopTicks_ScriptLoadUnload_Count >= MaintenanceLoopTicks_ScriptLoadUnload)
-                            {
-                                MaintenanceLoopTicks_ScriptLoadUnload_ResetCount = true;
-                                // LOAD / UNLOAD SCRIPTS
-                                if (m_ScriptEngine.m_ScriptManager != null)
-                                    m_ScriptEngine.m_ScriptManager.DoScriptLoadUnload();
+                                if (MaintenanceLoopTicks_ScriptLoadUnload_Count >= MaintenanceLoopTicks_ScriptLoadUnload)
+                                {
+                                    MaintenanceLoopTicks_ScriptLoadUnload_ResetCount = true;
+                                    // LOAD / UNLOAD SCRIPTS
+                                    if (m_ScriptEngine.m_ScriptManager != null)
+                                        m_ScriptEngine.m_ScriptManager.DoScriptLoadUnload();
+                                }
                             }
                         }
                     }
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs
index 60416eb..b861ad5 100644
--- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs
+++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs
@@ -84,7 +84,10 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
         public ScriptEngine()
         {
             Common.mySE = this;                 // For logging, just need any instance, doesn't matter
-            ScriptEngines.Add(this);            // Keep a list of ScriptEngines for shared threads to process all instances
+            lock (ScriptEngines)
+            {
+                ScriptEngines.Add(this); // Keep a list of ScriptEngines for shared threads to process all instances
+            }
         }
 
         public void InitializeEngine(Scene Sceneworld, IConfigSource config, bool HookUpToServer, ScriptManager newScriptManager)
@@ -107,7 +110,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
             newScriptManager.Start();
             m_ScriptManager = newScriptManager;
             m_AppDomainManager = new AppDomainManager(this);
-            m_ASYNCLSLCommandManager = new AsyncLSLCommandManager(this);
+            m_ASYNCLSLCommandManager = new AsyncLSLCommandManager();
             if (m_MaintenanceThread == null)
                 m_MaintenanceThread = new MaintenanceThread();
 
@@ -121,7 +124,10 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
         public void Shutdown()
         {
             // We are shutting down
-            ScriptEngines.Remove(this);
+            lock (ScriptEngines)
+            {
+                ScriptEngines.Remove(this);
+            }
         }
 
         ScriptServerInterfaces.RemoteEvents ScriptServerInterfaces.ScriptEngine.EventManager()
@@ -136,13 +142,6 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
 #endif
             RefreshConfigFileSeconds = ScriptConfigSource.GetInt("RefreshConfig", 30);
 
-            // Reload from disk? No!
-            //ConfigSource.Reload();
-            //if (File.Exists(OpenSim.Application.iniFilePath))
-            //{
-            //    //ConfigSource.Merge(new IniConfigSource(OpenSim.Application.iniFilePath));
-            //}
-        
 
         // Create a new object (probably not necessary?)
 //            ScriptConfigSource = ConfigSource.Configs[ScriptEngineName];
@@ -179,15 +178,6 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase
 
         #endregion
 
-        /// <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;
 
     }
 }
diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example
index 793fe5b..084d9f7 100644
--- a/bin/OpenSim.ini.example
+++ b/bin/OpenSim.ini.example
@@ -210,12 +210,6 @@ SleepTimeIfNoScriptExecutionMs=50
 ; Each AppDomain has some memory overhead. But leaving dead scripts in memory also has memory overhead.
 ScriptsPerAppDomain=1
 
-; Script loading / unloading sleep
-; How long load/unload thread should sleep if there is nothing to do
-; Higher value makes it respond slower when scripts are added/removed from prims
-; But once active it will process all in queue before sleeping again
-
-
 ; MaintenanceLoop
 ; How often to run maintenance loop
 ; Maintenance loop is doing: script compile/load, script unload, reload config, adjust running config and enforce max execution time
@@ -224,6 +218,10 @@ MaintenanceLoopms=50
 ; How many maintenanceloops between each of these.
 ; (if 2 then function will be executed every MaintenanceLoopms*2 ms)
 ; Script loading/unloading
+
+; How long load/unload thread should sleep if there is nothing to do
+; Higher value makes it respond slower when scripts are added/removed from prims
+; But once active it will process all in queue before sleeping again
 MaintenanceLoopTicks_ScriptLoadUnload=1
 
 ; Other tasks
-- 
cgit v1.1