diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptApi.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptApi.cs
index d2323f56d1..30e99b0d74 100644
--- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptApi.cs
+++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptApi.cs
@@ -46,6 +46,6 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
         /// /param>
         /// /param>
         void Initialize(
-            IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, EventWaitHandle coopSleepHandle);
+            IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle);
     }
 }
\ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs
index 17c270810f..b8fdd01d37 100644
--- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs
+++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs
@@ -25,16 +25,17 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-using log4net;
 using System;
-using OpenSim.Region.ScriptEngine.Shared;
+using System.Reflection;
+using OpenSim.Framework;
 using OpenSim.Region.Framework.Scenes;
 using OpenSim.Region.Framework.Interfaces;
-using OpenMetaverse;
-using Nini.Config;
 using OpenSim.Region.ScriptEngine.Interfaces;
+using OpenSim.Region.ScriptEngine.Shared;
 using Amib.Threading;
-using OpenSim.Framework;
+using log4net;
+using Nini.Config;
+using OpenMetaverse;
 
 namespace OpenSim.Region.ScriptEngine.Interfaces
 {
@@ -76,6 +77,38 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
         IConfigSource ConfigSource { get; }
         string ScriptEngineName { get; }
         string ScriptEnginePath { get; }
+
+        /// 
+        /// Return the name of the class that will be used for all running scripts.
+        /// 
+        /// 
+        /// Each class goes in its own assembly so we don't need to otherwise distinguish the class name.
+        /// 
+        string ScriptClassName { get; }
+
+        /// 
+        /// Return the name of the base class that will be used for all running scripts.
+        /// 
+        string ScriptBaseClassName { get; }
+
+        /// 
+        /// Assemblies that need to be referenced when compiling scripts.
+        /// 
+        /// 
+        /// These are currently additional to those always referenced by the compiler, BUT THIS MAY CHANGE IN THE 
+        /// FUTURE.
+        /// This can be null if there are no additional assemblies.
+        /// 
+        string[] ScriptReferencedAssemblies { get; }
+
+        /// 
+        /// Parameters for the generated script's constructor.
+        /// 
+        /// 
+        /// Can be null if there are no parameters
+        /// 
+        ParameterInfo[] ScriptBaseClassParameters { get; }
+
         IScriptApi GetApi(UUID itemID, string name);
     }
 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 3a7e1c7dc8..63f48003af 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -91,7 +91,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
         /// Used for script sleeps when we are using co-operative script termination.
         /// 
         /// null if co-operative script termination is not active  
-        EventWaitHandle m_coopSleepHandle;       
+        WaitHandle m_coopSleepHandle;       
 
         /// 
         /// The item that hosts this script
@@ -118,7 +118,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
         protected ISoundModule m_SoundModule = null;
 
         public void Initialize(
-            IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, EventWaitHandle coopSleepHandle)
+            IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle)
         {
             m_ScriptEngine = scriptEngine;
             m_host = host;
@@ -192,7 +192,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
         {
             if (m_coopSleepHandle == null)
                 System.Threading.Thread.Sleep(delay);
-            else if (m_coopSleepHandle.WaitOne(delay))
+            else
+                CheckForCoopTermination(delay);
+        }
+
+        /// 
+        /// Check for co-operative termination.
+        /// 
+        /// If called with 0, then just the check is performed with no wait.
+        protected virtual void CheckForCoopTermination(int delay)
+        {
+            if (m_coopSleepHandle.WaitOne(delay))
                 throw new ScriptCoopStopException();
         }
 
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
index a08ccc889e..1d6cb6d4dc 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
@@ -63,7 +63,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
         internal IScriptModuleComms m_comms = null;
 
         public void Initialize(
-            IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, EventWaitHandle coopSleepHandle)
+            IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle)
         {
             m_ScriptEngine = scriptEngine;
             m_host = host;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
index 981499ea92..90456721c0 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
@@ -63,7 +63,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
         internal IScriptModuleComms m_comms = null;
 
         public void Initialize(
-            IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, EventWaitHandle coopSleepHandle)
+            IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle)
         {
             m_ScriptEngine = scriptEngine;
             m_host = host;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 5c0ff1c6c4..14260705f1 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -143,7 +143,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
         protected IUrlModule m_UrlModule = null;
 
         public void Initialize(
-            IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, EventWaitHandle coopSleepHandle)
+            IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle)
         {
             m_ScriptEngine = scriptEngine;
             m_host = host;
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
index 97dd0f6122..985e598184 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs
@@ -49,6 +49,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
         private List m_warnings = new List();
         private IScriptModuleComms m_comms = null;
 
+        private bool m_insertCoopTerminationChecks;
+        private static string m_coopTerminationCheck = "opensim_reserved_CheckForCoopTermination();";
+
+        /// 
+        /// Keep a record of the previous node when we do the parsing.
+        /// 
+        /// 
+        /// We do this here because the parser generated by CSTools does not retain a reference to its parent node.
+        /// The previous node is required so we can correctly insert co-op termination checks when required.
+        /// 
+//        private SYMBOL m_previousNode;
+
         /// 
         /// Creates an 'empty' CSCodeGenerator instance.
         /// 
@@ -58,9 +70,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
             ResetCounters();
         }
 
-        public CSCodeGenerator(IScriptModuleComms comms)
+        public CSCodeGenerator(IScriptModuleComms comms, bool insertCoopTerminationChecks)
         {
             m_comms = comms;
+            m_insertCoopTerminationChecks = insertCoopTerminationChecks;
             ResetCounters();
         }
 
@@ -155,7 +168,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
             // here's the payload
             retstr += GenerateLine();
             foreach (SYMBOL s in m_astRoot.kids)
-                retstr += GenerateNode(s);
+                retstr += GenerateNode(m_astRoot, s);
 
             // close braces!
             m_braceCount--;
@@ -165,7 +178,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
 
             // Removes all carriage return characters which may be generated in Windows platform. Is there
             // cleaner way of doing this?
-            retstr=retstr.Replace("\r", "");
+            retstr = retstr.Replace("\r", "");
 
             return retstr;
         }
@@ -191,9 +204,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
         /// Recursively called to generate each type of node. Will generate this
         /// node, then all it's children.
         /// 
+        /// The parent node.
         /// The current node to generate code for.
         /// String containing C# code for SYMBOL s.
-        private string GenerateNode(SYMBOL s)
+        private string GenerateNode(SYMBOL previousSymbol, SYMBOL s)
         {
             string retstr = String.Empty;
 
@@ -207,11 +221,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
             else if (s is State)
                 retstr += GenerateState((State) s);
             else if (s is CompoundStatement)
-                retstr += GenerateCompoundStatement((CompoundStatement) s);
+                retstr += GenerateCompoundStatement(previousSymbol, (CompoundStatement) s);
             else if (s is Declaration)
                 retstr += GenerateDeclaration((Declaration) s);
             else if (s is Statement)
-                retstr += GenerateStatement((Statement) s);
+                retstr += GenerateStatement(previousSymbol, (Statement) s);
             else if (s is ReturnStatement)
                 retstr += GenerateReturnStatement((ReturnStatement) s);
             else if (s is JumpLabel)
@@ -261,7 +275,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
             else
             {
                 foreach (SYMBOL kid in s.kids)
-                    retstr += GenerateNode(kid);
+                    retstr += GenerateNode(s, kid);
             }
 
             return retstr;
@@ -295,7 +309,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
             retstr += GenerateLine(")");
 
             foreach (SYMBOL kid in remainingKids)
-                retstr += GenerateNode(kid);
+                retstr += GenerateNode(gf, kid);
 
             return retstr;
         }
@@ -312,7 +326,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
             foreach (SYMBOL s in gv.kids)
             {
                 retstr += Indent();
-                retstr += GenerateNode(s);
+                retstr += GenerateNode(gv, s);
                 retstr += GenerateLine(";");
             }
 
@@ -365,7 +379,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
             retstr += GenerateLine(")");
 
             foreach (SYMBOL kid in remainingKids)
-                retstr += GenerateNode(kid);
+                retstr += GenerateNode(se, kid);
 
             return retstr;
         }
@@ -404,7 +418,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
 
             foreach (SYMBOL s in al.kids)
             {
-                retstr += GenerateNode(s);
+                retstr += GenerateNode(al, s);
                 if (0 < comma--)
                     retstr += Generate(", ");
             }
@@ -417,7 +431,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
         /// 
         /// The CompoundStatement node.
         /// String containing C# code for CompoundStatement cs.
-        private string GenerateCompoundStatement(CompoundStatement cs)
+        private string GenerateCompoundStatement(SYMBOL previousSymbol, CompoundStatement cs)
         {
             string retstr = String.Empty;
 
@@ -425,8 +439,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
             retstr += GenerateIndentedLine("{");
             m_braceCount++;
 
+            if (m_insertCoopTerminationChecks)
+            {
+                // We have to check in event functions as well because the user can manually call these.
+                if (previousSymbol is GlobalFunctionDefinition 
+                    || previousSymbol is WhileStatement 
+                    || previousSymbol is DoWhileStatement 
+                    || previousSymbol is ForLoop
+                    || previousSymbol is StateEvent)
+                retstr += GenerateIndentedLine(m_coopTerminationCheck);
+            }
+
             foreach (SYMBOL kid in cs.kids)
-                retstr += GenerateNode(kid);
+                retstr += GenerateNode(cs, kid);
 
             // closing brace
             m_braceCount--;
@@ -450,13 +475,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
         /// 
         /// The Statement node.
         /// String containing C# code for Statement s.
-        private string GenerateStatement(Statement s)
+        private string GenerateStatement(SYMBOL previousSymbol, Statement s)
         {
             string retstr = String.Empty;
             bool printSemicolon = true;
 
             retstr += Indent();
 
+            if (m_insertCoopTerminationChecks)
+            {
+                // We have to check in event functions as well because the user can manually call these.
+                if (previousSymbol is GlobalFunctionDefinition 
+                    || previousSymbol is WhileStatement 
+                    || previousSymbol is DoWhileStatement 
+                    || previousSymbol is ForLoop
+                    || previousSymbol is StateEvent)
+                retstr += Generate(m_coopTerminationCheck);
+            }
+
             if (0 < s.kids.Count)
             {
                 // Jump label prints its own colon, we don't need a semicolon.
@@ -466,7 +502,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
                 // (MONO) error.
                 if (!(s.kids.Top is IdentExpression && 1 == s.kids.Count))
                     foreach (SYMBOL kid in s.kids)
-                        retstr += GenerateNode(kid);
+                        retstr += GenerateNode(s, kid);
             }
 
             if (printSemicolon)
@@ -487,10 +523,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
             List identifiers = new List();
             checkForMultipleAssignments(identifiers, a);
 
-            retstr += GenerateNode((SYMBOL) a.kids.Pop());
+            retstr += GenerateNode(a, (SYMBOL) a.kids.Pop());
             retstr += Generate(String.Format(" {0} ", a.AssignmentType), a);
             foreach (SYMBOL kid in a.kids)
-                retstr += GenerateNode(kid);
+                retstr += GenerateNode(a, kid);
 
             return retstr;
         }
@@ -563,7 +599,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
             retstr += Generate("return ", rs);
 
             foreach (SYMBOL kid in rs.kids)
-                retstr += GenerateNode(kid);
+                retstr += GenerateNode(rs, kid);
 
             return retstr;
         }
@@ -575,7 +611,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
         /// String containing C# code for JumpLabel jl.
         private string GenerateJumpLabel(JumpLabel jl)
         {
-            return Generate(String.Format("{0}:", CheckName(jl.LabelName)), jl) + " NoOp();\n";
+            string labelStatement;
+
+            if (m_insertCoopTerminationChecks)
+                labelStatement = m_coopTerminationCheck + "\n";
+            else
+                labelStatement = "NoOp();\n";
+
+            return Generate(String.Format("{0}: ", CheckName(jl.LabelName)), jl) + labelStatement;
         }
 
         /// 
@@ -598,14 +641,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
             string retstr = String.Empty;
 
             retstr += GenerateIndented("if (", ifs);
-            retstr += GenerateNode((SYMBOL) ifs.kids.Pop());
+            retstr += GenerateNode(ifs, (SYMBOL) ifs.kids.Pop());
             retstr += GenerateLine(")");
 
             // CompoundStatement handles indentation itself but we need to do it
             // otherwise.
             bool indentHere = ifs.kids.Top is Statement;
             if (indentHere) m_braceCount++;
-            retstr += GenerateNode((SYMBOL) ifs.kids.Pop());
+            retstr += GenerateNode(ifs, (SYMBOL) ifs.kids.Pop());
             if (indentHere) m_braceCount--;
 
             if (0 < ifs.kids.Count) // do it again for an else
@@ -614,7 +657,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
 
                 indentHere = ifs.kids.Top is Statement;
                 if (indentHere) m_braceCount++;
-                retstr += GenerateNode((SYMBOL) ifs.kids.Pop());
+                retstr += GenerateNode(ifs, (SYMBOL) ifs.kids.Pop());
                 if (indentHere) m_braceCount--;
             }
 
@@ -641,14 +684,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
             string retstr = String.Empty;
 
             retstr += GenerateIndented("while (", ws);
-            retstr += GenerateNode((SYMBOL) ws.kids.Pop());
+            retstr += GenerateNode(ws, (SYMBOL) ws.kids.Pop());
             retstr += GenerateLine(")");
 
             // CompoundStatement handles indentation itself but we need to do it
             // otherwise.
             bool indentHere = ws.kids.Top is Statement;
             if (indentHere) m_braceCount++;
-            retstr += GenerateNode((SYMBOL) ws.kids.Pop());
+            retstr += GenerateNode(ws, (SYMBOL) ws.kids.Pop());
             if (indentHere) m_braceCount--;
 
             return retstr;
@@ -669,11 +712,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
             // otherwise.
             bool indentHere = dws.kids.Top is Statement;
             if (indentHere) m_braceCount++;
-            retstr += GenerateNode((SYMBOL) dws.kids.Pop());
+            retstr += GenerateNode(dws, (SYMBOL) dws.kids.Pop());
             if (indentHere) m_braceCount--;
 
             retstr += GenerateIndented("while (", dws);
-            retstr += GenerateNode((SYMBOL) dws.kids.Pop());
+            retstr += GenerateNode(dws, (SYMBOL) dws.kids.Pop());
             retstr += GenerateLine(");");
 
             return retstr;
@@ -702,7 +745,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
             retstr += Generate("; ");
             // for (x = 0; x < 10; x++)
             //             ^^^^^^
-            retstr += GenerateNode((SYMBOL) fl.kids.Pop());
+            retstr += GenerateNode(fl, (SYMBOL) fl.kids.Pop());
             retstr += Generate("; ");
             // for (x = 0; x < 10; x++)
             //                     ^^^
@@ -713,7 +756,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
             // otherwise.
             bool indentHere = fl.kids.Top is Statement;
             if (indentHere) m_braceCount++;
-            retstr += GenerateNode((SYMBOL) fl.kids.Pop());
+            retstr += GenerateNode(fl, (SYMBOL) fl.kids.Pop());
             if (indentHere) m_braceCount--;
 
             return retstr;
@@ -758,7 +801,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
                 while (s is ParenthesisExpression)
                     s = (SYMBOL)s.kids.Pop();
                     
-                retstr += GenerateNode(s);
+                retstr += GenerateNode(fls, s);
                 if (0 < comma--)
                     retstr += Generate(", ");
             }
@@ -779,20 +822,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
             {
                 // special case handling for logical and/or, see Mantis 3174
                 retstr += "((bool)(";
-                retstr += GenerateNode((SYMBOL)be.kids.Pop());
+                retstr += GenerateNode(be, (SYMBOL)be.kids.Pop());
                 retstr += "))";
                 retstr += Generate(String.Format(" {0} ", be.ExpressionSymbol.Substring(0,1)), be);
                 retstr += "((bool)(";
                 foreach (SYMBOL kid in be.kids)
-                    retstr += GenerateNode(kid);
+                    retstr += GenerateNode(be, kid);
                 retstr += "))";
             }
             else
             {
-                retstr += GenerateNode((SYMBOL)be.kids.Pop());
+                retstr += GenerateNode(be, (SYMBOL)be.kids.Pop());
                 retstr += Generate(String.Format(" {0} ", be.ExpressionSymbol), be);
                 foreach (SYMBOL kid in be.kids)
-                    retstr += GenerateNode(kid);
+                    retstr += GenerateNode(be, kid);
             }
 
             return retstr;
@@ -808,7 +851,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
             string retstr = String.Empty;
 
             retstr += Generate(ue.UnarySymbol, ue);
-            retstr += GenerateNode((SYMBOL) ue.kids.Pop());
+            retstr += GenerateNode(ue, (SYMBOL) ue.kids.Pop());
 
             return retstr;
         }
@@ -824,7 +867,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
 
             retstr += Generate("(");
             foreach (SYMBOL kid in pe.kids)
-                retstr += GenerateNode(kid);
+                retstr += GenerateNode(pe, kid);
             retstr += Generate(")");
 
             return retstr;
@@ -861,7 +904,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
 
             // we wrap all typecasted statements in parentheses
             retstr += Generate(String.Format("({0}) (", te.TypecastType), te);
-            retstr += GenerateNode((SYMBOL) te.kids.Pop());
+            retstr += GenerateNode(te, (SYMBOL) te.kids.Pop());
             retstr += Generate(")");
 
             return retstr;
@@ -931,7 +974,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
             }
             
             foreach (SYMBOL kid in fc.kids)
-                retstr += GenerateNode(kid);
+                retstr += GenerateNode(fc, kid);
 
             retstr += Generate(")");
 
@@ -980,11 +1023,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
             string retstr = String.Empty;
 
             retstr += Generate(String.Format("new {0}(", vc.Type), vc);
-            retstr += GenerateNode((SYMBOL) vc.kids.Pop());
+            retstr += GenerateNode(vc, (SYMBOL) vc.kids.Pop());
             retstr += Generate(", ");
-            retstr += GenerateNode((SYMBOL) vc.kids.Pop());
+            retstr += GenerateNode(vc, (SYMBOL) vc.kids.Pop());
             retstr += Generate(", ");
-            retstr += GenerateNode((SYMBOL) vc.kids.Pop());
+            retstr += GenerateNode(vc, (SYMBOL) vc.kids.Pop());
             retstr += Generate(")");
 
             return retstr;
@@ -1000,13 +1043,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
             string retstr = String.Empty;
 
             retstr += Generate(String.Format("new {0}(", rc.Type), rc);
-            retstr += GenerateNode((SYMBOL) rc.kids.Pop());
+            retstr += GenerateNode(rc, (SYMBOL) rc.kids.Pop());
             retstr += Generate(", ");
-            retstr += GenerateNode((SYMBOL) rc.kids.Pop());
+            retstr += GenerateNode(rc, (SYMBOL) rc.kids.Pop());
             retstr += Generate(", ");
-            retstr += GenerateNode((SYMBOL) rc.kids.Pop());
+            retstr += GenerateNode(rc, (SYMBOL) rc.kids.Pop());
             retstr += Generate(", ");
-            retstr += GenerateNode((SYMBOL) rc.kids.Pop());
+            retstr += GenerateNode(rc, (SYMBOL) rc.kids.Pop());
             retstr += Generate(")");
 
             return retstr;
@@ -1024,7 +1067,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
             retstr += Generate(String.Format("new {0}(", lc.Type), lc);
 
             foreach (SYMBOL kid in lc.kids)
-                retstr += GenerateNode(kid);
+                retstr += GenerateNode(lc, kid);
 
             retstr += Generate(")");
 
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
index 03be2abf07..002e8529da 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs
@@ -31,6 +31,7 @@ using System.Collections.Generic;
 using System.Globalization;
 using System.Reflection;
 using System.IO;
+using System.Linq;
 using System.Text;
 using Microsoft.CSharp;
 //using Microsoft.JScript;
@@ -72,6 +73,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
         private bool CompileWithDebugInformation;
         private Dictionary AllowedCompilers = new Dictionary(StringComparer.CurrentCultureIgnoreCase);
         private Dictionary LanguageMapping = new Dictionary(StringComparer.CurrentCultureIgnoreCase);
+        private bool m_insertCoopTerminationCalls;
 
         private string FilePrefix;
         private string ScriptEnginesPath = null;
@@ -95,20 +97,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
         private Dictionary, KeyValuePair>> m_lineMaps =
             new Dictionary, KeyValuePair>>();
 
+        public bool in_startup = true;
+
         public Compiler(IScriptEngine scriptEngine)
         {
-            m_scriptEngine = scriptEngine;;
+            m_scriptEngine = scriptEngine;
             ScriptEnginesPath = scriptEngine.ScriptEnginePath;
             ReadConfig();
         }
 
-        public bool in_startup = true;
         public void ReadConfig()
         {
             // Get some config
             WriteScriptSourceToDebugFile = m_scriptEngine.Config.GetBoolean("WriteScriptSourceToDebugFile", false);
             CompileWithDebugInformation = m_scriptEngine.Config.GetBoolean("CompileWithDebugInformation", true);
             bool DeleteScriptsOnStartup = m_scriptEngine.Config.GetBoolean("DeleteScriptsOnStartup", true);
+            m_insertCoopTerminationCalls = m_scriptEngine.Config.GetString("ScriptStopStrategy", "abort") == "co-op";
 
             // Get file prefix from scriptengine name and make it file system safe:
             FilePrefix = "CommonCompiler";
@@ -386,7 +390,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
             if (language == enumCompileType.lsl)
             {
                 // Its LSL, convert it to C#
-                LSL_Converter = (ICodeConverter)new CSCodeGenerator(comms);
+                LSL_Converter = (ICodeConverter)new CSCodeGenerator(comms, m_insertCoopTerminationCalls);
                 compileScript = LSL_Converter.Convert(Script);
 
                 // copy converter warnings into our warnings.
@@ -411,16 +415,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
             {
                 case enumCompileType.cs:
                 case enumCompileType.lsl:
-                    compileScript = CreateCSCompilerScript(compileScript);
+                    compileScript = CreateCSCompilerScript(
+                        compileScript, 
+                        m_scriptEngine.ScriptClassName, 
+                        m_scriptEngine.ScriptBaseClassName, 
+                        m_scriptEngine.ScriptBaseClassParameters);
                     break;
                 case enumCompileType.vb:
-                    compileScript = CreateVBCompilerScript(compileScript);
+                    compileScript = CreateVBCompilerScript(
+                        compileScript, m_scriptEngine.ScriptClassName, m_scriptEngine.ScriptBaseClassName);
                     break;
 //                case enumCompileType.js:
-//                    compileScript = CreateJSCompilerScript(compileScript);
+//                    compileScript = CreateJSCompilerScript(compileScript, m_scriptEngine.ScriptBaseClassName);
 //                    break;
                 case enumCompileType.yp:
-                    compileScript = CreateYPCompilerScript(compileScript);
+                    compileScript = CreateYPCompilerScript(
+                        compileScript, m_scriptEngine.ScriptClassName,m_scriptEngine.ScriptBaseClassName);
                     break;
             }
 
@@ -451,43 +461,60 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
 //            return compileScript;
 //        }
 
-        private static string CreateCSCompilerScript(string compileScript)
+        private static string CreateCSCompilerScript(
+            string compileScript, string className, string baseClassName, ParameterInfo[] constructorParameters)
         {
-            compileScript = String.Empty +
-                "using OpenSim.Region.ScriptEngine.Shared; using System.Collections.Generic;\r\n" +
-                String.Empty + "namespace SecondLife { " +
-                String.Empty + "public class Script : OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass { \r\n" +
-                @"public Script() { } " +
-                compileScript +
-                "} }\r\n";
+            compileScript = string.Format(    
+@"using OpenSim.Region.ScriptEngine.Shared; 
+using System.Collections.Generic;
+
+namespace SecondLife 
+{{ 
+    public class {0} : {1} 
+    {{
+        public {0}({2}) : base({3}) {{}}
+{4}
+    }}
+}}",
+                className,
+                baseClassName, 
+                constructorParameters != null 
+                    ? string.Join(", ", Array.ConvertAll(constructorParameters, pi => pi.ToString())) 
+                    : "", 
+                constructorParameters != null 
+                    ? string.Join(", ", Array.ConvertAll(constructorParameters, pi => pi.Name)) 
+                    : "", 
+                compileScript);
+
             return compileScript;
         }
 
-        private static string CreateYPCompilerScript(string compileScript)
+        private static string CreateYPCompilerScript(string compileScript, string className, string baseClassName)
         {
             compileScript = String.Empty +
                        "using OpenSim.Region.ScriptEngine.Shared.YieldProlog; " +
                         "using OpenSim.Region.ScriptEngine.Shared; using System.Collections.Generic;\r\n" +
                         String.Empty + "namespace SecondLife { " +
-                        String.Empty + "public class Script : OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass  { \r\n" +
+                        String.Empty + "public class " + className + " : " + baseClassName + " { \r\n" +
                         //@"public Script() { } " +
                         @"static OpenSim.Region.ScriptEngine.Shared.YieldProlog.YP YP=null; " +
-                        @"public Script() {  YP= new OpenSim.Region.ScriptEngine.Shared.YieldProlog.YP(); } " +
-
+                        @"public " + className + "() {  YP= new OpenSim.Region.ScriptEngine.Shared.YieldProlog.YP(); } " +
                         compileScript +
                         "} }\r\n";
+
             return compileScript;
         }
 
-        private static string CreateVBCompilerScript(string compileScript)
+        private static string CreateVBCompilerScript(string compileScript, string className, string baseClassName)
         {
             compileScript = String.Empty +
                 "Imports OpenSim.Region.ScriptEngine.Shared: Imports System.Collections.Generic: " +
                 String.Empty + "NameSpace SecondLife:" +
-                String.Empty + "Public Class Script: Inherits OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass: " +
+                String.Empty + "Public Class " + className + ": Inherits " + baseClassName +
                 "\r\nPublic Sub New()\r\nEnd Sub: " +
                 compileScript +
                 ":End Class :End Namespace\r\n";
+
             return compileScript;
         }
 
@@ -549,6 +576,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
             parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
                     "OpenMetaverseTypes.dll"));
 
+            if (m_scriptEngine.ScriptReferencedAssemblies != null)
+                Array.ForEach(
+                    m_scriptEngine.ScriptReferencedAssemblies, 
+                    a => parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, a)));
+
             if (lang == enumCompileType.yp)
             {
                 parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index 75aea2b0b1..5bc585e15f 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -251,7 +251,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
         /// 
         /// 
         /// 
-        public void Load(AppDomain dom, string assembly, StateSource stateSource)
+        /// false if load failed, true if suceeded
+        public bool Load(AppDomain dom, string assembly, StateSource stateSource)
         {
             m_Assembly = assembly;
             m_stateSource = stateSource;
@@ -266,14 +267,56 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
     
             try
             {
-                if (dom != System.AppDomain.CurrentDomain)
-                    m_Script = (IScript)dom.CreateInstanceAndUnwrap(
-                            Path.GetFileNameWithoutExtension(assembly),
-                            "SecondLife.Script");
+                object[] constructorParams;
+
+                Assembly scriptAssembly = dom.Load(Path.GetFileNameWithoutExtension(assembly));
+                Type scriptType = scriptAssembly.GetType("SecondLife.XEngineScript");
+
+                if (scriptType != null)
+                {
+                    constructorParams = new object[] { m_coopSleepHandle };
+                }
+                else if (!m_coopTermination)
+                {
+                    scriptType = scriptAssembly.GetType("SecondLife.Script");
+                    constructorParams = null;
+                }
                 else
-                    m_Script = (IScript)Assembly.Load(
-                            Path.GetFileNameWithoutExtension(assembly)).CreateInstance(
-                            "SecondLife.Script");
+                {
+                    m_log.ErrorFormat(
+                        "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}.  You must remove all existing {6}* script DLL files before using enabling co-op termination"
+                        + ", either by setting DeleteScriptsOnStartup = true in [XEngine] for one run"
+                        + " or by deleting these files manually.",
+                        ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, assembly);
+
+                    return false;
+                }
+
+//                m_log.DebugFormat(
+//                    "[SCRIPT INSTANCE]: Looking to load {0} from assembly {1} in {2}", 
+//                    scriptType.FullName, Path.GetFileNameWithoutExtension(assembly), Engine.World.Name);
+
+                if (dom != System.AppDomain.CurrentDomain)
+                    m_Script 
+                        = (IScript)dom.CreateInstanceAndUnwrap(
+                            Path.GetFileNameWithoutExtension(assembly),
+                            scriptType.FullName,
+                            false,
+                            BindingFlags.Default,
+                            null,
+                            constructorParams,
+                            null,
+                            null);
+                else
+                    m_Script 
+                        = (IScript)scriptAssembly.CreateInstance(
+                            scriptType.FullName, 
+                            false, 
+                            BindingFlags.Default, 
+                            null, 
+                            constructorParams, 
+                            null, 
+                            null);
 
                 //ILease lease = (ILease)RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass);
                 //RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass);
@@ -282,8 +325,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
             catch (Exception e)
             {
                 m_log.ErrorFormat(
-                    "[SCRIPT INSTANCE]: Error loading assembly {0}.  Exception {1}{2}",
-                    assembly, e.Message, e.StackTrace);
+                    "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}.  Error loading assembly {6}.  Exception {7}{8}",
+                    ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, assembly, e.Message, e.StackTrace);
+
+                return false;
             }
 
             try
@@ -301,10 +346,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
             catch (Exception e)
             {
                 m_log.ErrorFormat(
-                    "[SCRIPT INSTANCE]: Error loading script instance from assembly {0}.  Exception {1}{2}",
-                    assembly, e.Message, e.StackTrace);
+                    "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}.  Error initializing script instance.  Exception {6}{7}",
+                    ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, e.Message, e.StackTrace);
 
-                return;
+                return false;
             }
 
             m_SaveState = true;
@@ -357,15 +402,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
                     else
                     {
                         m_log.WarnFormat(
-                            "[SCRIPT INSTANCE]: Unable to load script state file {0} for script {1} {2} in {3} {4} (assembly {5}).  Memory limit exceeded",
-                            savedState, ScriptName, ItemID, PrimName, ObjectID, assembly);
+                            "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}.  Unable to load script state file {6}.  Memory limit exceeded.",
+                            ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, savedState);
                     }
                 }
                 catch (Exception e)
                 {
                      m_log.ErrorFormat(
-                         "[SCRIPT INSTANCE]: Unable to load script state file {0} for script {1} {2} in {3} {4} (assembly {5}).  XML is {6}.  Exception {7}{8}",
-                         savedState, ScriptName, ItemID, PrimName, ObjectID, assembly, xml, e.Message, e.StackTrace);
+                         "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}.  Unable to load script state file {6}.  XML is {7}.  Exception {8}{9}",
+                         ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, savedState, xml, e.Message, e.StackTrace);
                 }
             }
 //            else
@@ -376,6 +421,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
 //                    presence.ControllingClient.SendAgentAlertMessage("Compile successful", false);
 
 //            }
+
+            return true;
         }
 
         public void Init()
@@ -552,9 +599,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
                 }
                 else
                 {
-                    m_log.DebugFormat(
-                        "[SCRIPT INSTANCE]: Co-operatively stopping script {0} {1} in {2} {3}",
-                        ScriptName, ItemID, PrimName, ObjectID);
+                    if (DebugLevel >= 1)
+                        m_log.DebugFormat(
+                            "[SCRIPT INSTANCE]: Co-operatively stopping script {0} {1} in {2} {3}",
+                            ScriptName, ItemID, PrimName, ObjectID);
 
                     // This will terminate the event on next handle check by the script.
                     m_coopSleepHandle.Set();
@@ -563,9 +611,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
                     // checking is implemented.  May want to allow a shorter timeout option later.
                     if (workItem.Wait(TimeSpan.MaxValue))
                     {
-                        m_log.DebugFormat(
-                            "[SCRIPT INSTANCE]: Co-operatively stopped script {0} {1} in {2} {3}",
-                            ScriptName, ItemID, PrimName, ObjectID);
+                        if (DebugLevel >= 1)
+                            m_log.DebugFormat(
+                                "[SCRIPT INSTANCE]: Co-operatively stopped script {0} {1} in {2} {3}",
+                                ScriptName, ItemID, PrimName, ObjectID);
 
                         return true;
                     }
@@ -876,9 +925,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
                             }
                             else if ((e is TargetInvocationException) && (e.InnerException is ScriptCoopStopException))
                             {
-                                m_log.DebugFormat(
-                                    "[SCRIPT INSTANCE]: Script {0}.{1} in event {2}, state {3} stopped co-operatively.",
-                                    PrimName, ScriptName, data.EventName, State);
+                                if (DebugLevel >= 1)
+                                    m_log.DebugFormat(
+                                        "[SCRIPT INSTANCE]: Script {0}.{1} in event {2}, state {3} stopped co-operatively.",
+                                        PrimName, ScriptName, data.EventName, State);
                             }
                         }
                     }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs
index 8c3e9e0b47..52d75a0d31 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs
@@ -50,14 +50,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
         private TestScene m_scene;
         private OpenSim.Region.ScriptEngine.XEngine.XEngine m_xEngine;
 
-        private AutoResetEvent m_chatEvent = new AutoResetEvent(false);
-        private AutoResetEvent m_stoppedEvent = new AutoResetEvent(false);
+        private AutoResetEvent m_chatEvent;
+        private AutoResetEvent m_stoppedEvent;
 
         private OSChatMessage m_osChatMessageReceived;
 
-        [TestFixtureSetUp]
+        [SetUp]
         public void Init()
         {
+            m_osChatMessageReceived = null;
+            m_chatEvent = new AutoResetEvent(false);
+            m_stoppedEvent = new AutoResetEvent(false);
+
             //AppDomain.CurrentDomain.SetData("APPBASE", Environment.CurrentDirectory + "/bin");
 //            Console.WriteLine(AppDomain.CurrentDomain.BaseDirectory);
             m_xEngine = new OpenSim.Region.ScriptEngine.XEngine.XEngine();
@@ -77,7 +81,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
 
             xEngineConfig.Set("ScriptStopStrategy", "co-op");
 
-            m_scene = new SceneHelpers().SetupScene("My Test", UUID.Random(), 1000, 1000, configSource);
+            // Make sure loops aren't actually being terminated by a script delay wait.
+            xEngineConfig.Set("ScriptDelayFactor", 0);
+
+            // This is really just set for debugging the test.
+            xEngineConfig.Set("WriteScriptSourceToDebugFile", true);
+
+            // Set to false if we need to debug test so the old scripts don't get wiped before each separate test
+//            xEngineConfig.Set("DeleteScriptsOnStartup", false);
+
+            // This is not currently used at all for co-op termination.  Bumping up to demonstrate that co-op termination
+            // has an effect - without it tests will fail due to a 120 second wait for the event to finish.
+            xEngineConfig.Set("WaitForEventCompletionOnScriptStop", 120000);
+
+            m_scene = new SceneHelpers().SetupScene("My Test", TestHelpers.ParseTail(0x9999), 1000, 1000, configSource);
             SceneHelpers.SetupSceneModules(m_scene, configSource, m_xEngine);
             m_scene.StartScripts();
         }
@@ -95,12 +112,218 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
             TestHelpers.InMethod();
 //            TestHelpers.EnableLogging();
 
+            string script = 
+@"default
+{    
+    state_entry()
+    {
+        llSay(0, ""Thin Lizzy"");
+        llSleep(60);
+    }
+}";
+
+            TestStop(script);
+        }
+
+        [Test]
+        public void TestStopOnLongSingleStatementForLoop()
+        {
+            TestHelpers.InMethod();
+//            TestHelpers.EnableLogging();
+
+            string script = 
+@"default
+{    
+    state_entry()
+    {
+        integer i = 0;
+        llSay(0, ""Thin Lizzy"");
+        
+        for (i = 0; i < 2147483647; i++)        
+            llSay(0, ""Iter "" + (string)i);
+    }
+}";
+
+            TestStop(script);
+        }
+
+        [Test]
+        public void TestStopOnLongCompoundStatementForLoop()
+        {
+            TestHelpers.InMethod();
+//            TestHelpers.EnableLogging();
+
+            string script = 
+@"default
+{    
+    state_entry()
+    {
+        integer i = 0;
+        llSay(0, ""Thin Lizzy"");
+        
+        for (i = 0; i < 2147483647; i++) 
+        {
+            llSay(0, ""Iter "" + (string)i);
+        }
+    }
+}";
+
+            TestStop(script);
+        }
+
+        [Test]
+        public void TestStopOnLongSingleStatementWhileLoop()
+        {
+            TestHelpers.InMethod();
+//            TestHelpers.EnableLogging();
+
+            string script = 
+@"default
+{    
+    state_entry()
+    {
+        integer i = 0;
+        llSay(0, ""Thin Lizzy"");
+
+        while (1 == 1)        
+            llSay(0, ""Iter "" + (string)i++);
+    }
+}";
+
+            TestStop(script);
+        }
+
+        [Test]
+        public void TestStopOnLongCompoundStatementWhileLoop()
+        {
+            TestHelpers.InMethod();
+//            TestHelpers.EnableLogging();
+
+            string script = 
+@"default
+{    
+    state_entry()
+    {
+        integer i = 0;
+        llSay(0, ""Thin Lizzy"");
+
+        while (1 == 1) 
+        {
+            llSay(0, ""Iter "" + (string)i++);
+        }
+    }
+}";
+
+            TestStop(script);
+        }
+
+        [Test]
+        public void TestStopOnLongDoWhileLoop()
+        {
+            TestHelpers.InMethod();
+//            TestHelpers.EnableLogging();
+
+            string script = 
+@"default
+{    
+    state_entry()
+    {
+        integer i = 0;
+        llSay(0, ""Thin Lizzy"");
+
+        do 
+        {
+            llSay(0, ""Iter "" + (string)i++);
+} while (1 == 1);
+    }
+}";
+
+            TestStop(script);
+        }
+
+        [Test]
+        public void TestStopOnInfiniteJumpLoop()
+        {
+            TestHelpers.InMethod();
+            TestHelpers.EnableLogging();
+
+            string script = 
+@"default
+{    
+    state_entry()
+    {
+        integer i = 0;
+        llSay(0, ""Thin Lizzy"");
+
+        @p1;      
+        llSay(0, ""Iter "" + (string)i++);
+        jump p1;
+    }
+}";
+
+            TestStop(script);
+        }
+
+        [Test]
+        public void TestStopOnInfiniteUserFunctionCallLoop()
+        {
+            TestHelpers.InMethod();
+//            TestHelpers.EnableLogging();
+
+            string script = 
+@"
+integer i = 0;
+
+ufn1()
+{
+  llSay(0, ""Iter ufn1() "" + (string)i++);
+  ufn1();
+}
+
+default
+{    
+    state_entry()
+    {
+        integer i = 0;
+        llSay(0, ""Thin Lizzy"");
+
+        ufn1();
+    }
+}";
+
+            TestStop(script);
+        }
+
+        [Test]
+        public void TestStopOnInfiniteManualEventCallLoop()
+        {
+            TestHelpers.InMethod();
+//            TestHelpers.EnableLogging();
+
+            string script = 
+@"default
+{    
+    state_entry()
+    {
+        integer i = 0;
+        llSay(0, ""Thin Lizzy"");
+
+        llSay(0, ""Iter"" + (string)i++);
+        default_event_state_entry();
+    }
+}";
+
+            TestStop(script);
+        }
+
+        private void TestStop(string script)
+        {
             UUID userId = TestHelpers.ParseTail(0x1);
 //            UUID objectId = TestHelpers.ParseTail(0x100);
 //            UUID itemId = TestHelpers.ParseTail(0x3);
-            string itemName = "TestStopOnObjectDerezLongSleep() Item";
+            string itemName = "TestStop() Item";
 
-            SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, "TestStopOnObjectDerezLongSleep", 0x100);
+            SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, "TestStop", 0x100);
             m_scene.AddNewSceneObject(so, true);
 
             InventoryItemBase itemTemplate = new InventoryItemBase();
@@ -111,15 +334,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
 
             m_scene.EventManager.OnChatFromWorld += OnChatFromWorld;
 
-            SceneObjectPart partWhereRezzed = m_scene.RezNewScript(userId, itemTemplate, 
-@"default
-{    
-    state_entry()
-    {
-        llSay(0, ""Thin Lizzy"");
-        llSleep(60);
-    }
-}");
+            SceneObjectPart partWhereRezzed = m_scene.RezNewScript(userId, itemTemplate, script);
 
             TaskInventoryItem rezzedItem = partWhereRezzed.Inventory.GetInventoryItem(itemName);
 
@@ -129,7 +344,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
             Console.WriteLine("Script started with message [{0}]", m_osChatMessageReceived.Message);
 
             // FIXME: This is a very poor way of trying to avoid a low-probability race condition where the script
-            // executes llSay() but has not started the sleep before we try to stop it.
+            // executes llSay() but has not started the next statement before we try to stop it.
             Thread.Sleep(1000);
 
             // We need a way of carrying on if StopScript() fail, since it won't return if the script isn't actually
@@ -148,7 +363,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
 
         private void OnChatFromWorld(object sender, OSChatMessage oscm)
         {
-//            Console.WriteLine("Got chat [{0}]", oscm.Message);
+            m_scene.EventManager.OnChatFromWorld -= OnChatFromWorld;
+            Console.WriteLine("Got chat [{0}]", oscm.Message);
 
             m_osChatMessageReceived = oscm;
             m_chatEvent.Set();
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Api/Runtime/XEngineScriptBase.cs b/OpenSim/Region/ScriptEngine/XEngine/Api/Runtime/XEngineScriptBase.cs
new file mode 100644
index 0000000000..f4211c8286
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/Api/Runtime/XEngineScriptBase.cs
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the OpenSimulator Project nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Runtime.Remoting;
+using System.Runtime.Remoting.Lifetime;
+using System.Security.Permissions;
+using System.Threading;
+using System.Reflection;
+using System.Collections;
+using System.Collections.Generic;
+using OpenSim.Region.ScriptEngine.Interfaces;
+using OpenSim.Region.ScriptEngine.Shared;
+using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
+
+namespace OpenSim.Region.ScriptEngine.XEngine.ScriptBase
+{
+    public class XEngineScriptBase : ScriptBaseClass
+    {
+        /// 
+        /// Used for script sleeps when we are using co-operative script termination.
+        /// 
+        /// null if co-operative script termination is not active  
+        WaitHandle m_coopSleepHandle;
+
+        public XEngineScriptBase(WaitHandle coopSleepHandle) : base()
+        {
+            m_coopSleepHandle = coopSleepHandle;
+        }
+
+        public void opensim_reserved_CheckForCoopTermination()
+        {
+            if (m_coopSleepHandle != null && m_coopSleepHandle.WaitOne(0))
+                throw new ScriptCoopStopException();
+        }
+    }
+}
\ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
index 9405075e51..afde685d68 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
@@ -52,7 +52,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
         {
             myScriptEngine = _ScriptEngine;
 
-            m_log.Info("[XEngine] Hooking up to server events");
+//            m_log.Info("[XEngine] Hooking up to server events");
             myScriptEngine.World.EventManager.OnAttach += attach;
             myScriptEngine.World.EventManager.OnObjectGrab += touch_start;
             myScriptEngine.World.EventManager.OnObjectGrabbing += touch;
@@ -69,7 +69,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
             myScriptEngine.World.EventManager.OnScriptLandColliderStart += land_collision_start;
             myScriptEngine.World.EventManager.OnScriptLandColliding += land_collision;
             myScriptEngine.World.EventManager.OnScriptLandColliderEnd += land_collision_end;
-            IMoneyModule money=myScriptEngine.World.RequestModuleInterface();
+            IMoneyModule money = myScriptEngine.World.RequestModuleInterface();
             if (money != null)
             {
                 money.OnObjectPaid+=HandleObjectPaid;
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs
similarity index 100%
rename from OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs
rename to OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 72646f6ccb..d4832195e1 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -46,13 +46,15 @@ using OpenSim.Framework;
 using OpenSim.Framework.Console;
 using OpenSim.Region.Framework.Scenes;
 using OpenSim.Region.Framework.Interfaces;
+using OpenSim.Region.ScriptEngine.Interfaces;
 using OpenSim.Region.ScriptEngine.Shared;
 using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
 using OpenSim.Region.ScriptEngine.Shared.CodeTools;
 using OpenSim.Region.ScriptEngine.Shared.Instance;
 using OpenSim.Region.ScriptEngine.Shared.Api;
 using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
-using OpenSim.Region.ScriptEngine.Interfaces;
+using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
+using OpenSim.Region.ScriptEngine.XEngine.ScriptBase;
 using Timer = OpenSim.Region.ScriptEngine.Shared.Api.Plugins.Timer;
 
 using ScriptCompileQueue = OpenSim.Framework.LocklessQueue