From c8afc8523b9caf931afb3d5b3f9874b26b866a77 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 17 Jan 2013 23:39:09 +0000 Subject: [PATCH 01/24] Implement non-wait co-operative termination of scripts for XEngine in addition to termination on wait. This involves inserting opensim_reserved_CheckForCoopTermination() calls in lsl -> c# translation at any place where the script could be in a loop with no wait calls. These places are for, while, do-while, label, user function call and manual event function call. Call goes through to an XEngineScriptBase which extends ScriptBase. IEngine is extended to supply necessary engine-specific parent class references and constructor parameters to Compiler. Unfortunately, since XEngineScriptBase has to be passed WaitHandle in its constructor, older compiled scripts will fail to load with an error on the OpenSim console. Such scripts will need to be recompiled, either by removing all *.dll files from the bin/ScriptEngines/ or by setting DeleteScriptsOnStartup = true in [XEngine] for one run. Automatic recompilation may be implemented in a later commit. This feature should not yet be used, default remains termination with Thread.Abort() which will work as normal once scripts are recompiled. --- .../ScriptEngine/Interfaces/IScriptEngine.cs | 35 ++++- .../Shared/Api/Implementation/LSL_Api.cs | 12 +- .../Shared/CodeTools/CSCodeGenerator.cs | 133 ++++++++++++------ .../ScriptEngine/Shared/CodeTools/Compiler.cs | 66 ++++++--- .../Shared/Instance/ScriptInstance.cs | 24 +++- .../XEngine/Api/Runtime/XEngineScriptBase.cs | 61 ++++++++ .../Region/ScriptEngine/XEngine/XEngine.cs | 17 ++- prebuild.xml | 36 +++++ 8 files changed, 307 insertions(+), 77 deletions(-) create mode 100644 OpenSim/Region/ScriptEngine/XEngine/Api/Runtime/XEngineScriptBase.cs diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs index 17c270810f..20dcac9855 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,30 @@ namespace OpenSim.Region.ScriptEngine.Interfaces IConfigSource ConfigSource { get; } string ScriptEngineName { get; } string ScriptEnginePath { 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 d47fd6b5ac..cee10a8e6e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -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/CodeTools/CSCodeGenerator.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs index 97dd0f6122..002f9b8a44 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 ForLoopStatement + || 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..7432202ad9 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,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools { case enumCompileType.cs: case enumCompileType.lsl: - compileScript = CreateCSCompilerScript(compileScript); + compileScript = CreateCSCompilerScript( + compileScript, m_scriptEngine.ScriptBaseClassName, m_scriptEngine.ScriptBaseClassParameters); break; case enumCompileType.vb: - compileScript = CreateVBCompilerScript(compileScript); + compileScript = CreateVBCompilerScript(compileScript, 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.ScriptBaseClassName); break; } @@ -451,43 +456,59 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools // return compileScript; // } - private static string CreateCSCompilerScript(string compileScript) + private static string CreateCSCompilerScript( + string compileScript, 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 Script : {0} + {{ + public Script({1}) : base({2}) {{}} +{3} + }} +}}", + 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 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 Script : " + baseClassName + " { \r\n" + //@"public Script() { } " + @"static OpenSim.Region.ScriptEngine.Shared.YieldProlog.YP YP=null; " + @"public Script() { 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 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 Script: Inherits " + baseClassName + "\r\nPublic Sub New()\r\nEnd Sub: " + compileScript + ":End Class :End Namespace\r\n"; + return compileScript; } @@ -549,6 +570,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..e6ec0e1867 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -267,13 +267,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance try { if (dom != System.AppDomain.CurrentDomain) - m_Script = (IScript)dom.CreateInstanceAndUnwrap( + m_Script + = (IScript)dom.CreateInstanceAndUnwrap( Path.GetFileNameWithoutExtension(assembly), - "SecondLife.Script"); + "SecondLife.Script", + false, + BindingFlags.Default, + null, + new object[] { m_coopSleepHandle }, + null, + null, + null); else - m_Script = (IScript)Assembly.Load( - Path.GetFileNameWithoutExtension(assembly)).CreateInstance( - "SecondLife.Script"); + m_Script + = (IScript)Assembly.Load(Path.GetFileNameWithoutExtension(assembly)).CreateInstance( + "SecondLife.Script", + false, + BindingFlags.Default, + null, + new object[] { m_coopSleepHandle }, + null, + null); //ILease lease = (ILease)RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass); //RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass); 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/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index a17a0188bb..8a0259079b 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -53,6 +53,7 @@ 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.XEngine.ScriptBase; using Timer = OpenSim.Region.ScriptEngine.Shared.Api.Plugins.Timer; using ScriptCompileQueue = OpenSim.Framework.LocklessQueue; @@ -176,6 +177,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine get { return "XEngine"; } } + public string ScriptBaseClassName { get; private set; } + + public ParameterInfo[] ScriptBaseClassParameters { get; private set; } + + public string[] ScriptReferencedAssemblies { get; private set; } + public Scene World { get { return m_Scene; } @@ -230,6 +237,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine m_ScriptConfig = configSource.Configs["XEngine"]; m_ConfigSource = configSource; + + ScriptBaseClassName = typeof(XEngineScriptBase).FullName; + ScriptBaseClassParameters = typeof(XEngineScriptBase).GetConstructor(new Type[] { typeof(WaitHandle) }).GetParameters(); + ScriptReferencedAssemblies = new string[] { Path.GetFileName(typeof(XEngineScriptBase).Assembly.Location) }; + + Console.WriteLine("ASSEMBLY NAME: {0}", ScriptReferencedAssemblies[0]); } public void AddRegion(Scene scene) @@ -1179,7 +1192,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine } catch (Exception e) { -// m_log.ErrorFormat("[XEngine]: Exception when rezzing script {0}{1}", e.Message, e.StackTrace); +// m_log.ErrorFormat( +// "[XEngine]: Exception when rezzing script with item ID {0}, {1}{2}", +// itemID, e.Message, e.StackTrace); // try // { diff --git a/prebuild.xml b/prebuild.xml index abf8f364d7..4019e0bf33 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -2423,6 +2423,40 @@ + + + + ../../../../../../bin/ + + + + + ../../../../../../bin/ + + + + ../../../../../../bin/ + + + + + + + + + + + + + + + + + + + + + @@ -2453,6 +2487,7 @@ + @@ -2460,6 +2495,7 @@ + From 607558fe21ab6c200789a148e419f39730d3c420 Mon Sep 17 00:00:00 2001 From: Talun Date: Mon, 14 Jan 2013 18:17:33 +0000 Subject: [PATCH 02/24] New constants for llGetObjectDetails New constants for llGetObjectDetails OBJECT_CHARACTER_TIME, OBJECT_ROOT, OBJECT_ATTACHED_POINT, OBJECT_PATHFINDING_TYPE, OBJECT_PHYSICS, OBJECT_PHANTOM and OBJECT_TEMP_ON_REZ also Pathfining constants, 3 of which are used by llGetObjectDetails --- .../Shared/Api/Implementation/LSL_Api.cs | 75 +++++++++++++++++++ .../Shared/Api/Runtime/LSL_Constants.cs | 17 +++++ 2 files changed, 92 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 50597b7fda..db5add19e6 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -10590,6 +10590,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case ScriptBaseClass.OBJECT_PHYSICS_COST: ret.Add(new LSL_Float(0)); break; + case ScriptBaseClass.OBJECT_CHARACTER_TIME: // Pathfinding + ret.Add(new LSL_Float(0)); + break; + case ScriptBaseClass.OBJECT_ROOT: + SceneObjectPart p = av.ParentPart; + if (p != null) + { + ret.Add(new LSL_String(p.ParentGroup.RootPart.UUID.ToString())); + } + else + { + ret.Add(new LSL_String(id)); + } + break; + case ScriptBaseClass.OBJECT_ATTACHED_POINT: + ret.Add(new LSL_Integer(0)); + break; + case ScriptBaseClass.OBJECT_PATHFINDING_TYPE: // Pathfinding + ret.Add(new LSL_Integer(ScriptBaseClass.OPT_AVATAR)); + break; + case ScriptBaseClass.OBJECT_PHYSICS: + ret.Add(new LSL_Integer(0)); + break; + case ScriptBaseClass.OBJECT_PHANTOM: + ret.Add(new LSL_Integer(0)); + break; + case ScriptBaseClass.OBJECT_TEMP_ON_REZ: + ret.Add(new LSL_Integer(0)); + break; default: // Invalid or unhandled constant. ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL)); @@ -10685,6 +10714,52 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // The value returned in SL for normal prims looks like the prim count ret.Add(new LSL_Float(0)); break; + case ScriptBaseClass.OBJECT_CHARACTER_TIME: // Pathfinding + ret.Add(new LSL_Float(0)); + break; + case ScriptBaseClass.OBJECT_ROOT: + ret.Add(new LSL_String(obj.ParentGroup.RootPart.UUID.ToString())); + break; + case ScriptBaseClass.OBJECT_ATTACHED_POINT: + ret.Add(new LSL_Integer(obj.ParentGroup.AttachmentPoint)); + break; + case ScriptBaseClass.OBJECT_PATHFINDING_TYPE: + byte pcode = obj.Shape.PCode; + if (obj.ParentGroup.AttachmentPoint != 0 + || pcode == (byte)PCode.Grass + || pcode == (byte)PCode.Tree + || pcode == (byte)PCode.NewTree) + { + ret.Add(new LSL_Integer(ScriptBaseClass.OPT_OTHER)); + } + else + { + ret.Add(new LSL_Integer(ScriptBaseClass.OPT_LEGACY_LINKSET)); + } + break; + case ScriptBaseClass.OBJECT_PHYSICS: + if (obj.ParentGroup.AttachmentPoint != 0) + { + ret.Add(new LSL_Integer(0)); // Always false if attached + } + else + { + ret.Add(new LSL_Integer(obj.ParentGroup.UsesPhysics ? 1 : 0)); + } + break; + case ScriptBaseClass.OBJECT_PHANTOM: + if (obj.ParentGroup.AttachmentPoint != 0) + { + ret.Add(new LSL_Integer(0)); // Always false if attached + } + else + { + ret.Add(new LSL_Integer(obj.ParentGroup.IsPhantom ? 1 : 0)); + } + break; + case ScriptBaseClass.OBJECT_TEMP_ON_REZ: + ret.Add(new LSL_Integer(obj.ParentGroup.IsTemporary ? 1 : 0)); + break; default: // Invalid or unhandled constant. ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL)); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index 880841b5d9..9bf1a64cf9 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -556,6 +556,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int OBJECT_SERVER_COST = 14; public const int OBJECT_STREAMING_COST = 15; public const int OBJECT_PHYSICS_COST = 16; + public const int OBJECT_CHARACTER_TIME = 17; + public const int OBJECT_ROOT = 18; + public const int OBJECT_ATTACHED_POINT = 19; + public const int OBJECT_PATHFINDING_TYPE = 20; + public const int OBJECT_PHYSICS = 21; + public const int OBJECT_PHANTOM = 22; + public const int OBJECT_TEMP_ON_REZ = 23; + + // Pathfinding types + public const int OPT_OTHER = -1; + public const int OPT_LEGACY_LINKSET = 0; + public const int OPT_AVATAR = 1; + public const int OPT_CHARACTER = 2; + public const int OPT_WALKABLE = 3; + public const int OPT_STATIC_OBSTACLE = 4; + public const int OPT_MATERIAL_VOLUME = 5; + public const int OPT_EXCLUSION_VOLUME = 6; // for llGetAgentList public const int AGENT_LIST_PARCEL = 1; From 49d674c74d6390b33e3d5d655df70eb7adda6065 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 22 Jan 2013 00:35:56 +0000 Subject: [PATCH 03/24] refactor: rename XEngineTest to more descriptive XEngineBasicTests --- .../XEngine/Tests/{XEngineTest.cs => XEngineBasicTests.cs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename OpenSim/Region/ScriptEngine/XEngine/Tests/{XEngineTest.cs => XEngineBasicTests.cs} (100%) 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 From cd446c32d6d4c6453dbc85c5d8ac75c65a6db979 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 22 Jan 2013 00:59:46 +0000 Subject: [PATCH 04/24] Add regression test TestStopOnLongForLoop() --- .../Instance/Tests/CoopTerminationTests.cs | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs index 8c3e9e0b47..c23d7a6501 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs @@ -146,6 +146,65 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests Assert.That(running, Is.False); } + [Test] + public void TestStopOnLongForLoop() + { + TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); + + UUID userId = TestHelpers.ParseTail(0x1); +// UUID objectId = TestHelpers.ParseTail(0x100); +// UUID itemId = TestHelpers.ParseTail(0x3); + string itemName = "TestStopOnLongForLoop() Item"; + + SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, "TestStopOnLongForLoop", 0x100); + m_scene.AddNewSceneObject(so, true); + + InventoryItemBase itemTemplate = new InventoryItemBase(); +// itemTemplate.ID = itemId; + itemTemplate.Name = itemName; + itemTemplate.Folder = so.UUID; + itemTemplate.InvType = (int)InventoryType.LSL; + + m_scene.EventManager.OnChatFromWorld += OnChatFromWorld; + + SceneObjectPart partWhereRezzed = m_scene.RezNewScript(userId, itemTemplate, +@"default +{ + state_entry() + { + llSay(0, ""Thin Lizzy""); + integer i = 0; + for (i = 0; i < 2147483647; i++) + llSay(0, ""Iter "" + (string)i); + } +}"); + + TaskInventoryItem rezzedItem = partWhereRezzed.Inventory.GetInventoryItem(itemName); + + // Wait for the script to start the event before we try stopping it. + m_chatEvent.WaitOne(60000); + + 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. + Thread.Sleep(1000); + + // We need a way of carrying on if StopScript() fail, since it won't return if the script isn't actually + // stopped. This kind of multi-threading is far from ideal in a regression test. + new Thread(() => { m_xEngine.StopScript(rezzedItem.ItemID); m_stoppedEvent.Set(); }).Start(); + + if (!m_stoppedEvent.WaitOne(30000)) + Assert.Fail("Script did not co-operatively stop."); + + bool running; + TaskInventoryItem scriptItem = partWhereRezzed.Inventory.GetInventoryItem(itemName); + Assert.That( + SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, scriptItem, out running), Is.True); + Assert.That(running, Is.False); + } + private void OnChatFromWorld(object sender, OSChatMessage oscm) { // Console.WriteLine("Got chat [{0}]", oscm.Message); From 1730de14a4cfd78d6d87f12b5b1dcd268aba7fbd Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 22 Jan 2013 01:00:53 +0000 Subject: [PATCH 05/24] minor: comment out Console.WriteLine debugging message in XEngine --- OpenSim/Region/ScriptEngine/XEngine/XEngine.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 8a0259079b..c1f9271f46 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -242,7 +242,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine ScriptBaseClassParameters = typeof(XEngineScriptBase).GetConstructor(new Type[] { typeof(WaitHandle) }).GetParameters(); ScriptReferencedAssemblies = new string[] { Path.GetFileName(typeof(XEngineScriptBase).Assembly.Location) }; - Console.WriteLine("ASSEMBLY NAME: {0}", ScriptReferencedAssemblies[0]); +// Console.WriteLine("ASSEMBLY NAME: {0}", ScriptReferencedAssemblies[0]); } public void AddRegion(Scene scene) From 419f8e0f76ba765044d2ac29e03ee714356f42e3 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 22 Jan 2013 01:08:24 +0000 Subject: [PATCH 06/24] Increase WaitForEventCompletionOnScriptStop to 120 secs to show that the co-op setting is active in its regression tests. --- .../Shared/Instance/Tests/CoopTerminationTests.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs index c23d7a6501..53b992d7f3 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs @@ -77,6 +77,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests xEngineConfig.Set("ScriptStopStrategy", "co-op"); + // 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", UUID.Random(), 1000, 1000, configSource); SceneHelpers.SetupSceneModules(m_scene, configSource, m_xEngine); m_scene.StartScripts(); From a558f9797d3a2af00f6472adfc46ad5363d9bc1b Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 22 Jan 2013 01:13:45 +0000 Subject: [PATCH 07/24] factor out common code in existing co-op termination regression tests --- .../Instance/Tests/CoopTerminationTests.cs | 89 ++++++------------- 1 file changed, 29 insertions(+), 60 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs index 53b992d7f3..952ae401ad 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs @@ -99,23 +99,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests TestHelpers.InMethod(); // TestHelpers.EnableLogging(); - UUID userId = TestHelpers.ParseTail(0x1); -// UUID objectId = TestHelpers.ParseTail(0x100); -// UUID itemId = TestHelpers.ParseTail(0x3); - string itemName = "TestStopOnObjectDerezLongSleep() Item"; - - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, "TestStopOnObjectDerezLongSleep", 0x100); - m_scene.AddNewSceneObject(so, true); - - InventoryItemBase itemTemplate = new InventoryItemBase(); -// itemTemplate.ID = itemId; - itemTemplate.Name = itemName; - itemTemplate.Folder = so.UUID; - itemTemplate.InvType = (int)InventoryType.LSL; - - m_scene.EventManager.OnChatFromWorld += OnChatFromWorld; - - SceneObjectPart partWhereRezzed = m_scene.RezNewScript(userId, itemTemplate, + string script = @"default { state_entry() @@ -123,31 +107,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests llSay(0, ""Thin Lizzy""); llSleep(60); } -}"); +}"; - TaskInventoryItem rezzedItem = partWhereRezzed.Inventory.GetInventoryItem(itemName); - - // Wait for the script to start the event before we try stopping it. - m_chatEvent.WaitOne(60000); - - 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. - Thread.Sleep(1000); - - // We need a way of carrying on if StopScript() fail, since it won't return if the script isn't actually - // stopped. This kind of multi-threading is far from ideal in a regression test. - new Thread(() => { m_xEngine.StopScript(rezzedItem.ItemID); m_stoppedEvent.Set(); }).Start(); - - if (!m_stoppedEvent.WaitOne(30000)) - Assert.Fail("Script did not co-operatively stop."); - - bool running; - TaskInventoryItem scriptItem = partWhereRezzed.Inventory.GetInventoryItem(itemName); - Assert.That( - SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, scriptItem, out running), Is.True); - Assert.That(running, Is.False); + TestStop(script); } [Test] @@ -156,23 +118,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests TestHelpers.InMethod(); // TestHelpers.EnableLogging(); - UUID userId = TestHelpers.ParseTail(0x1); -// UUID objectId = TestHelpers.ParseTail(0x100); -// UUID itemId = TestHelpers.ParseTail(0x3); - string itemName = "TestStopOnLongForLoop() Item"; - - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, "TestStopOnLongForLoop", 0x100); - m_scene.AddNewSceneObject(so, true); - - InventoryItemBase itemTemplate = new InventoryItemBase(); -// itemTemplate.ID = itemId; - itemTemplate.Name = itemName; - itemTemplate.Folder = so.UUID; - itemTemplate.InvType = (int)InventoryType.LSL; - - m_scene.EventManager.OnChatFromWorld += OnChatFromWorld; - - SceneObjectPart partWhereRezzed = m_scene.RezNewScript(userId, itemTemplate, + string script = @"default { state_entry() @@ -182,7 +128,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests for (i = 0; i < 2147483647; i++) llSay(0, ""Iter "" + (string)i); } -}"); +}"; + + TestStop(script); + } + + private void TestStop(string script) + { + UUID userId = TestHelpers.ParseTail(0x1); +// UUID objectId = TestHelpers.ParseTail(0x100); +// UUID itemId = TestHelpers.ParseTail(0x3); + string itemName = "TestStop() Item"; + + SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, "TestStop", 0x100); + m_scene.AddNewSceneObject(so, true); + + InventoryItemBase itemTemplate = new InventoryItemBase(); +// itemTemplate.ID = itemId; + itemTemplate.Name = itemName; + itemTemplate.Folder = so.UUID; + itemTemplate.InvType = (int)InventoryType.LSL; + + m_scene.EventManager.OnChatFromWorld += OnChatFromWorld; + + SceneObjectPart partWhereRezzed = m_scene.RezNewScript(userId, itemTemplate, script); TaskInventoryItem rezzedItem = partWhereRezzed.Inventory.GetInventoryItem(itemName); @@ -192,7 +161,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 From c6ba27d096a3008bc0128aebddf4d2e9708d2498 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 22 Jan 2013 01:23:10 +0000 Subject: [PATCH 08/24] Fix bug in generating termination checks in compound statement for loop. Add regression test for this case. --- .../Shared/CodeTools/CSCodeGenerator.cs | 2 +- .../Instance/Tests/CoopTerminationTests.cs | 28 +++++++++++++++++-- 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs index 002f9b8a44..985e598184 100644 --- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs +++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/CSCodeGenerator.cs @@ -445,7 +445,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools if (previousSymbol is GlobalFunctionDefinition || previousSymbol is WhileStatement || previousSymbol is DoWhileStatement - || previousSymbol is ForLoopStatement + || previousSymbol is ForLoop || previousSymbol is StateEvent) retstr += GenerateIndentedLine(m_coopTerminationCheck); } diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs index 952ae401ad..c83a6bac20 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs @@ -76,12 +76,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests xEngineConfig.Set("AppDomainLoading", "false"); xEngineConfig.Set("ScriptStopStrategy", "co-op"); + xEngineConfig.Set("WriteScriptSourceToDebugFile", true); // 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", UUID.Random(), 1000, 1000, configSource); + m_scene = new SceneHelpers().SetupScene("My Test", TestHelpers.ParseTail(0x9999), 1000, 1000, configSource); SceneHelpers.SetupSceneModules(m_scene, configSource, m_xEngine); m_scene.StartScripts(); } @@ -113,7 +114,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests } [Test] - public void TestStopOnLongForLoop() + public void TestStopOnLongSingleStatementForLoop() { TestHelpers.InMethod(); // TestHelpers.EnableLogging(); @@ -133,6 +134,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests TestStop(script); } + [Test] + public void TestStopOnLongCompoundStatementForLoop() + { + TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); + + string script = +@"default +{ + state_entry() + { + llSay(0, ""Thin Lizzy""); + integer i = 0; + for (i = 0; i < 2147483647; i++) + { + llSay(0, ""Iter "" + (string)i); + } + } +}"; + + TestStop(script); + } + private void TestStop(string script) { UUID userId = TestHelpers.ParseTail(0x1); From fbdfe43d75cb99066ce5fcfa803b135aff6e1fe0 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 22 Jan 2013 01:40:18 +0000 Subject: [PATCH 09/24] Add single and comound while loop co-op termination test --- .../Instance/Tests/CoopTerminationTests.cs | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs index c83a6bac20..87951f9d54 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs @@ -157,6 +157,50 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests TestStop(script); } + [Test] + public void TestStopOnLongSingleStatementWhileLoop() + { + TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); + + string script = +@"default +{ + state_entry() + { + 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() + { + llSay(0, ""Thin Lizzy""); + + while (1 == 1) + { + llSay(0, ""Iter "" + (string)i); + } + } +}"; + + TestStop(script); + } + private void TestStop(string script) { UUID userId = TestHelpers.ParseTail(0x1); From cf0b5e4f279e36e506c46a8c1d980f015fe5cfb2 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 22 Jan 2013 01:53:10 +0000 Subject: [PATCH 10/24] Add do-while co-op termination test Minor changes to scripts in other tests. --- .../Instance/Tests/CoopTerminationTests.cs | 32 +++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs index 87951f9d54..33d217562c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs @@ -124,8 +124,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests { state_entry() { - llSay(0, ""Thin Lizzy""); integer i = 0; + llSay(0, ""Thin Lizzy""); + for (i = 0; i < 2147483647; i++) llSay(0, ""Iter "" + (string)i); } @@ -145,8 +146,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests { state_entry() { - llSay(0, ""Thin Lizzy""); integer i = 0; + llSay(0, ""Thin Lizzy""); + for (i = 0; i < 2147483647; i++) { llSay(0, ""Iter "" + (string)i); @@ -168,6 +170,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests { state_entry() { + integer i = 0; llSay(0, ""Thin Lizzy""); while (1 == 1) @@ -189,6 +192,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests { state_entry() { + integer i = 0; llSay(0, ""Thin Lizzy""); while (1 == 1) @@ -201,6 +205,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests 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); + } + private void TestStop(string script) { UUID userId = TestHelpers.ParseTail(0x1); From b93e8020e25ab22973e5ef25cc563ee39a9c3f66 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 22 Jan 2013 02:16:10 +0000 Subject: [PATCH 11/24] Add regression test for co-op stop of an infinite jump loop Also fixes bug in do-while test Improves detection of failure due to invalid script in test Sets up xengine anew for each test rather than once for the while testsuite to improve isolation between tests. Stop listening for chat after the first 'script is running' chat is received to reduce test run time. --- .../Instance/Tests/CoopTerminationTests.cs | 49 ++++++++++++++++--- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs index 33d217562c..3365c92b0b 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(); @@ -76,8 +80,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests xEngineConfig.Set("AppDomainLoading", "false"); xEngineConfig.Set("ScriptStopStrategy", "co-op"); + + // 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); @@ -174,7 +183,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests llSay(0, ""Thin Lizzy""); while (1 == 1) - llSay(0, ""Iter "" + (string)i); + llSay(0, ""Iter "" + (string)i++); } }"; @@ -197,7 +206,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests while (1 == 1) { - llSay(0, ""Iter "" + (string)i); + llSay(0, ""Iter "" + (string)i++); } } }"; @@ -221,8 +230,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests do { - llSay(0, ""Iter "" + (string)i); - } while (1 == 1) + 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; } }"; @@ -276,7 +308,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(); From 679dc811dda95bd3d037e9bd691a9cd10fbf032a Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 22 Jan 2013 02:22:58 +0000 Subject: [PATCH 12/24] Add regression test for co-op termination on infinite user function call regression. Such a script would probably run out of stack pretty quickly anyway. --- .../Instance/Tests/CoopTerminationTests.cs | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs index 3365c92b0b..149a27bd38 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs @@ -261,6 +261,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests 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); + } + private void TestStop(string script) { UUID userId = TestHelpers.ParseTail(0x1); From 0727784186ec906804e0b6d3cdc17877f1da9e06 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 22 Jan 2013 02:26:04 +0000 Subject: [PATCH 13/24] Set script delay factor to 0 in co-op termination tests This is to ensure loops aren't actually terminating from a wait on an LSL function. This was not the case with any of the existing tests. --- .../ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs index 149a27bd38..019375df47 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs @@ -81,6 +81,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests xEngineConfig.Set("ScriptStopStrategy", "co-op"); + // 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); From 9a4914e58cace98228e12e4d2e44064cc1db20bf Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 22 Jan 2013 02:32:40 +0000 Subject: [PATCH 14/24] Add co-op termination regression test for infinite recursive manual call on event function. Such code would normally terminate quickly with a stack overflow exception anyway. --- .../Instance/Tests/CoopTerminationTests.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs index 019375df47..bd882f9dec 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs @@ -294,6 +294,28 @@ default 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); From cf168194e5968c1fab33266bdbb57465f303860b Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 23 Jan 2013 02:28:27 +0000 Subject: [PATCH 15/24] If ScriptStopStrategy hasn't been set to co-op in [XEngine] config, then continue to generate C# that is functionality identical to historical generation This is to eliminate disruption until co-op termination has been well-tested. In non co-op mode, XEngine will continue to load DLLs of the existing Script class and the new XEngineScript class. Moving to co-op mode still requires existing script DLL deletion to force recompilation, either manually or by setting DeleteScriptsOnStartup = true for one run. This change also means that scripts which fail to initialize do not still show up as running scripts. --- .../ScriptEngine/Interfaces/IScriptEngine.cs | 8 ++++ .../ScriptEngine/Shared/CodeTools/Compiler.cs | 30 +++++++----- .../Shared/Instance/ScriptInstance.cs | 48 +++++++++++++++---- .../Instance/Tests/CoopTerminationTests.cs | 2 +- .../Region/ScriptEngine/XEngine/XEngine.cs | 26 +++++++--- prebuild.xml | 1 + 6 files changed, 88 insertions(+), 27 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs index 20dcac9855..b8fdd01d37 100644 --- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs +++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs @@ -78,6 +78,14 @@ namespace OpenSim.Region.ScriptEngine.Interfaces 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. /// diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs index 7432202ad9..002e8529da 100644 --- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs +++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs @@ -416,16 +416,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools case enumCompileType.cs: case enumCompileType.lsl: compileScript = CreateCSCompilerScript( - compileScript, m_scriptEngine.ScriptBaseClassName, m_scriptEngine.ScriptBaseClassParameters); + compileScript, + m_scriptEngine.ScriptClassName, + m_scriptEngine.ScriptBaseClassName, + m_scriptEngine.ScriptBaseClassParameters); break; case enumCompileType.vb: - compileScript = CreateVBCompilerScript(compileScript, m_scriptEngine.ScriptBaseClassName); + compileScript = CreateVBCompilerScript( + compileScript, m_scriptEngine.ScriptClassName, m_scriptEngine.ScriptBaseClassName); break; // case enumCompileType.js: // compileScript = CreateJSCompilerScript(compileScript, m_scriptEngine.ScriptBaseClassName); // break; case enumCompileType.yp: - compileScript = CreateYPCompilerScript(compileScript, m_scriptEngine.ScriptBaseClassName); + compileScript = CreateYPCompilerScript( + compileScript, m_scriptEngine.ScriptClassName,m_scriptEngine.ScriptBaseClassName); break; } @@ -457,7 +462,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools // } private static string CreateCSCompilerScript( - string compileScript, string baseClassName, ParameterInfo[] constructorParameters) + string compileScript, string className, string baseClassName, ParameterInfo[] constructorParameters) { compileScript = string.Format( @"using OpenSim.Region.ScriptEngine.Shared; @@ -465,12 +470,13 @@ using System.Collections.Generic; namespace SecondLife {{ - public class Script : {0} + public class {0} : {1} {{ - public Script({1}) : base({2}) {{}} -{3} + public {0}({2}) : base({3}) {{}} +{4} }} }}", + className, baseClassName, constructorParameters != null ? string.Join(", ", Array.ConvertAll(constructorParameters, pi => pi.ToString())) @@ -483,28 +489,28 @@ namespace SecondLife return compileScript; } - private static string CreateYPCompilerScript(string compileScript, string baseClassName) + 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 : " + baseClassName + " { \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, string baseClassName) + 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 " + baseClassName + + String.Empty + "Public Class " + className + ": Inherits " + baseClassName + "\r\nPublic Sub New()\r\nEnd Sub: " + compileScript + ":End Class :End Namespace\r\n"; diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index e6ec0e1867..4cfcb750a5 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,26 +267,53 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance try { + 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_log.ErrorFormat( + "[SCRIPT INSTANCE]: You must remove all existing script DLLs before using enabling co-op termination" + + ", either by setting DeleteScriptsOnStartup = true in [XEngine] for one run" + + " or by deleting all *.dll* files in the relevant bin/ScriptEngines// directory"); + + 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), - "SecondLife.Script", + scriptType.FullName, false, BindingFlags.Default, null, - new object[] { m_coopSleepHandle }, - null, + constructorParams, null, null); else m_Script - = (IScript)Assembly.Load(Path.GetFileNameWithoutExtension(assembly)).CreateInstance( - "SecondLife.Script", + = (IScript)scriptAssembly.CreateInstance( + scriptType.FullName, false, BindingFlags.Default, null, - new object[] { m_coopSleepHandle }, + constructorParams, null, null); @@ -298,6 +326,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance m_log.ErrorFormat( "[SCRIPT INSTANCE]: Error loading assembly {0}. Exception {1}{2}", assembly, e.Message, e.StackTrace); + + return false; } try @@ -318,7 +348,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance "[SCRIPT INSTANCE]: Error loading script instance from assembly {0}. Exception {1}{2}", assembly, e.Message, e.StackTrace); - return; + return false; } m_SaveState = true; @@ -390,6 +420,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance // presence.ControllingClient.SendAgentAlertMessage("Compile successful", false); // } + + return true; } public void Init() diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs index bd882f9dec..52d75a0d31 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs @@ -245,7 +245,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests public void TestStopOnInfiniteJumpLoop() { TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); + TestHelpers.EnableLogging(); string script = @"default diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index c1f9271f46..604924bd0e 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -46,13 +46,14 @@ 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; @@ -177,6 +178,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine get { return "XEngine"; } } + public string ScriptClassName { get; private set; } + public string ScriptBaseClassName { get; private set; } public ParameterInfo[] ScriptBaseClassParameters { get; private set; } @@ -238,9 +241,18 @@ namespace OpenSim.Region.ScriptEngine.XEngine m_ScriptConfig = configSource.Configs["XEngine"]; m_ConfigSource = configSource; - ScriptBaseClassName = typeof(XEngineScriptBase).FullName; - ScriptBaseClassParameters = typeof(XEngineScriptBase).GetConstructor(new Type[] { typeof(WaitHandle) }).GetParameters(); - ScriptReferencedAssemblies = new string[] { Path.GetFileName(typeof(XEngineScriptBase).Assembly.Location) }; + if (m_ScriptConfig.GetString("ScriptStopStrategy", "abort") == "co-op") + { + ScriptClassName = "XEngineScript"; + ScriptBaseClassName = typeof(XEngineScriptBase).FullName; + ScriptBaseClassParameters = typeof(XEngineScriptBase).GetConstructor(new Type[] { typeof(WaitHandle) }).GetParameters(); + ScriptReferencedAssemblies = new string[] { Path.GetFileName(typeof(XEngineScriptBase).Assembly.Location) }; + } + else + { + ScriptClassName = "Script"; + ScriptBaseClassName = typeof(ScriptBaseClass).FullName; + } // Console.WriteLine("ASSEMBLY NAME: {0}", ScriptReferencedAssemblies[0]); } @@ -1122,7 +1134,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine } m_log.DebugFormat( - "[XEngine] Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", + "[XEngine]: Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); @@ -1143,6 +1155,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine lock (m_AddingAssemblies) { m_Compiler.PerformScriptCompile(script, assetID.ToString(), item.OwnerID, out assembly, out linemap); + if (!m_AddingAssemblies.ContainsKey(assembly)) { m_AddingAssemblies[assembly] = 1; } else { @@ -1303,7 +1316,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine startParam, postOnRez, m_MaxScriptQueue); - instance.Load(m_AppDomains[appDomain], assembly, stateSource); + if (!instance.Load(m_AppDomains[appDomain], assembly, stateSource)) + return false; // if (DebugLevel >= 1) // m_log.DebugFormat( diff --git a/prebuild.xml b/prebuild.xml index 4019e0bf33..e891433cf6 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -2487,6 +2487,7 @@ + From a0d460e6bfa64a6c43ff327dcf19b696cc380fbb Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 18 Jan 2013 12:10:03 -0800 Subject: [PATCH 16/24] BulletSim: remove the unused RestoreBodyDependencies used by linksets and vehicles and clean up code by removing their kludgyness. --- .../BulletSPlugin/BSLinksetCompound.cs | 7 ------- .../BulletSPlugin/BSLinksetConstraints.cs | 8 -------- .../Region/Physics/BulletSPlugin/BSPrim.cs | 20 ++----------------- 3 files changed, 2 insertions(+), 33 deletions(-) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index 27d8ad0ef9..0077da766a 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs @@ -290,13 +290,6 @@ public sealed class BSLinksetCompound : BSLinkset return ret; } - // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', - // this routine will restore the removed constraints. - // Called at taint-time!! - public override void RestoreBodyDependencies(BSPrim child) - { - } - // When the linkset is built, the child shape is added to the compound shape relative to the // root shape. The linkset then moves around but this does not move the actual child // prim. The child prim's location must be recomputed based on the location of the root shape. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs index 89f186c206..3011465dec 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs @@ -110,14 +110,6 @@ public sealed class BSLinksetConstraints : BSLinkset return ret; } - // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', - // this routine will restore the removed constraints. - // Called at taint-time!! - public override void RestoreBodyDependencies(BSPrim child) - { - // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints. - } - // ================================================================ // Add a new child to the linkset. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index e6b8507337..b37a1f8522 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -1606,11 +1606,6 @@ public sealed class BSPrim : BSPhysObject // Called at taint-time!!! public void CreateGeomAndObject(bool forceRebuild) { - // If this prim is part of a linkset, we must remove and restore the physical - // links if the body is rebuilt. - bool needToRestoreLinkset = false; - bool needToRestoreVehicle = false; - // Create the correct physical representation for this type of object. // Updates PhysBody and PhysShape with the new information. // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. @@ -1619,21 +1614,10 @@ public sealed class BSPrim : BSPhysObject // Called if the current prim body is about to be destroyed. // Remove all the physical dependencies on the old body. // (Maybe someday make the changing of BSShape an event to be subscribed to by BSLinkset, ...) - needToRestoreLinkset = Linkset.RemoveBodyDependencies(this); - needToRestoreVehicle = _vehicle.RemoveBodyDependencies(this); + Linkset.RemoveBodyDependencies(this); + _vehicle.RemoveBodyDependencies(this); }); - if (needToRestoreLinkset) - { - // If physical body dependencies were removed, restore them - Linkset.RestoreBodyDependencies(this); - } - if (needToRestoreVehicle) - { - // If physical body dependencies were removed, restore them - _vehicle.RestoreBodyDependencies(this); - } - // Make sure the properties are set on the new object UpdatePhysicalParameters(); return; From 775fd6f8cc27c80974b59a79be477a99950a7095 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Fri, 18 Jan 2013 12:12:45 -0800 Subject: [PATCH 17/24] BulletSim: fix build break introduced by previous commit --- OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 580ea4e689..1e3e5d8f9f 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -261,11 +261,6 @@ public abstract class BSLinkset // Called at taint-time!! public abstract bool RemoveBodyDependencies(BSPrim child); - // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', - // this routine will restore the removed constraints. - // Called at taint-time!! - public abstract void RestoreBodyDependencies(BSPrim child); - // ================================================================ protected virtual float ComputeLinksetMass() { From c1371ab786a699ce91693e6e575bb81144a79c57 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 23 Jan 2013 08:28:36 -0800 Subject: [PATCH 18/24] BulletSim: working on COM --- .../Physics/BulletSPlugin/BSApiTemplate.cs | 19 +++++++++++++++++++ .../BulletSPlugin/BSLinksetCompound.cs | 7 ++++--- .../Region/Physics/BulletSPlugin/BSPrim.cs | 15 +++++++++++---- .../Physics/BulletSPlugin/BulletSimTODO.txt | 2 ++ 4 files changed, 36 insertions(+), 7 deletions(-) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs index bc163eb946..2828cab23d 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs @@ -140,6 +140,25 @@ public struct EntityProperties public Vector3 Velocity; public Vector3 Acceleration; public Vector3 RotationalVelocity; + + public override string ToString() + { + StringBuilder buff = new StringBuilder(); + buff.Append(""); + return buff.ToString(); + } } // Format of this structure must match the definition in the C++ code diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index 0077da766a..d8e4028506 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs @@ -377,7 +377,7 @@ public sealed class BSLinksetCompound : BSLinkset // Constraint linksets are rebuilt every time. // Note that this works for rebuilding just the root after a linkset is taken apart. // Called at taint time!! - private bool disableCOM = true; // disable until we get this debugged + private bool disableCOM = false; // disable until we get this debugged private void RecomputeLinksetCompound() { try @@ -400,8 +400,9 @@ public sealed class BSLinksetCompound : BSLinkset } // DEBUG DEBUG else { - centerOfMass = ComputeLinksetGeometricCenter(); - centerDisplacement = centerOfMass - LinksetRoot.RawPosition; + centerOfMass = ComputeLinksetCenterOfMass(); + // 'centerDisplacement' is the value to *add* to all the shape offsets + centerDisplacement = LinksetRoot.RawPosition - centerOfMass; // Since we're displacing the center of the shape, we need to move the body in the world LinksetRoot.PositionDisplacement = centerDisplacement; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index b37a1f8522..dad7250960 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -336,6 +336,7 @@ public sealed class BSPrim : BSPhysObject } } } + /* Disable. Presume whoever is setting displacement is already adjusting position, etc. // Override to have position displacement immediately update the physical position. // A feeble attempt to keep the sim and physical positions in sync // Must be called at taint time. @@ -355,6 +356,7 @@ public sealed class BSPrim : BSPhysObject }); } } + */ // Check that the current position is sane and, if not, modify the position to make it so. // Check for being below terrain and being out of bounds. @@ -371,11 +373,11 @@ public sealed class BSPrim : BSPhysObject return ret; } - float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); + float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition); OMV.Vector3 upForce = OMV.Vector3.Zero; if (RawPosition.Z < terrainHeight) { - DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); + DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, RawPosition, terrainHeight); float targetHeight = terrainHeight + (Size.Z / 2f); // If the object is below ground it just has to be moved up because pushing will // not get it through the terrain @@ -1637,7 +1639,11 @@ public sealed class BSPrim : BSPhysObject // entprop.RotationalVelocity = OMV.Vector3.Zero; } + DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG + // Assign directly to the local variables so the normal set actions do not happen + + // Undo any center-of-mass displacement that might have been done. entprop.Position -= PositionDisplacement; _position = entprop.Position; _orientation = entprop.Rotation; @@ -1645,6 +1651,8 @@ public sealed class BSPrim : BSPhysObject _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; + DetailLog("{0},BSPrim.UpdateProperties,afterAssign,entprop={1}", LocalID, entprop); // DEBUG DEBUG + // The sanity check can change the velocity and/or position. if (IsPhysical && PositionSanityCheck(true)) { @@ -1653,8 +1661,7 @@ public sealed class BSPrim : BSPhysObject } OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; // DEBUG DEBUG DEBUG - DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}", - LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity); + DetailLog("{0},BSPrim.UpdateProperties,call,entProp={1},dir={2}", LocalID, entprop, direction); // remember the current and last set values LastEntityProperties = CurrentEntityProperties; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt index 41bab2601d..801f6908ee 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt @@ -1,5 +1,7 @@ CURRENT PRIORITIES ================================================= +Deleting a linkset while standing on the root will leave the physical shape of the root behind. + Not sure if it is because standing on it. Done with large prim linksets. Child movement in linkset (don't rebuild linkset) Vehicle angular vertical attraction vehicle angular banking From a5e9c665f08059fef16d0b0875697cb08e16351e Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 23 Jan 2013 09:09:17 -0800 Subject: [PATCH 19/24] BulletSim: center-of-gravity linkset changes. Not working yet. Conflicts: OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs --- .../BulletSPlugin/BSLinksetCompound.cs | 5 ++++- .../Region/Physics/BulletSPlugin/BSParam.cs | 7 ++---- .../Region/Physics/BulletSPlugin/BSPrim.cs | 22 +------------------ .../Region/Physics/BulletSPlugin/BSScene.cs | 4 ++-- 4 files changed, 9 insertions(+), 29 deletions(-) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index d8e4028506..2c8dd233d6 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs @@ -407,6 +407,9 @@ public sealed class BSLinksetCompound : BSLinkset // Since we're displacing the center of the shape, we need to move the body in the world LinksetRoot.PositionDisplacement = centerDisplacement; + // This causes the root prim position to be set properly based on the new PositionDisplacement + LinksetRoot.ForcePosition = LinksetRoot.RawPosition; + // Update the local transform for the root child shape so it is offset from the <0,0,0> which is COM PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, 0, -centerDisplacement, OMV.Quaternion.Identity, false); DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,com={1},rootPos={2},centerDisp={3}", LinksetRoot.LocalID, centerOfMass, LinksetRoot.RawPosition, centerDisplacement); @@ -438,7 +441,7 @@ public sealed class BSLinksetCompound : BSLinkset if (cPrim.PhysShape.isNativeShape) { - // A native shape is turning into a hull collision shape because native + // A native shape is turned into a hull collision shape because native // shapes are not shared so we have to hullify it so it will be tracked // and freed at the correct time. This also solves the scaling problem // (native shapes scaled but hull/meshes are assumed to not be). diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs index da7438a4ae..9460daff70 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs @@ -645,11 +645,8 @@ public static class BSParam entries.Add(new PhysParameterEntry(pd.name, pd.desc)); } - // make the list in alphabetical order for estetic reasons - entries.Sort(delegate(PhysParameterEntry ppe1, PhysParameterEntry ppe2) - { - return ppe1.name.CompareTo(ppe2.name); - }); + // make the list alphabetical for estetic reasons + entries.Sort((ppe1, ppe2) => { return ppe1.name.CompareTo(ppe2.name); }); SettableParameters = entries.ToArray(); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index dad7250960..ee2bfa093a 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -322,6 +322,7 @@ public sealed class BSPrim : BSPhysObject }); } } + public override OMV.Vector3 ForcePosition { get { _position = PhysicsScene.PE.GetPosition(PhysBody) - PositionDisplacement; @@ -336,27 +337,6 @@ public sealed class BSPrim : BSPhysObject } } } - /* Disable. Presume whoever is setting displacement is already adjusting position, etc. - // Override to have position displacement immediately update the physical position. - // A feeble attempt to keep the sim and physical positions in sync - // Must be called at taint time. - public override OMV.Vector3 PositionDisplacement - { - get - { - return base.PositionDisplacement; - } - set - { - base.PositionDisplacement = value; - PhysicsScene.TaintedObject(PhysicsScene.InTaintTime, "BSPrim.setPosition", delegate() - { - if (PhysBody.HasPhysicalBody) - PhysicsScene.PE.SetTranslation(PhysBody, _position + base.PositionDisplacement, _orientation); - }); - } - } - */ // Check that the current position is sane and, if not, modify the position to make it so. // Check for being below terrain and being out of bounds. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 8075b73b05..34fd2a0531 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -708,8 +708,8 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // TriggerPreStepEvent // DoOneTimeTaints // Step() - // ProcessAndForwardCollisions - // ProcessAndForwardPropertyUpdates + // ProcessAndSendToSimulatorCollisions + // ProcessAndSendToSimulatorPropertyUpdates // TriggerPostStepEvent // Calls to the PhysicsActors can't directly call into the physics engine From 13182904da897be1dad0bb86d8099bd0956ffac4 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 23 Jan 2013 09:11:01 -0800 Subject: [PATCH 20/24] BulletSim: small change to center-of-mass computation left out last commit --- OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index ee2bfa093a..731ab7ba52 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -1621,10 +1621,15 @@ public sealed class BSPrim : BSPhysObject DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG - // Assign directly to the local variables so the normal set actions do not happen - // Undo any center-of-mass displacement that might have been done. - entprop.Position -= PositionDisplacement; + if (PositionDisplacement != OMV.Vector3.Zero) + { + // Correct for any rotation around the center-of-mass + // TODO!!! + entprop.Position -= PositionDisplacement; + } + + // Assign directly to the local variables so the normal set actions do not happen _position = entprop.Position; _orientation = entprop.Rotation; _velocity = entprop.Velocity; From a7b810ddeebda8b13af3ab9fbeb24bef1a8094c6 Mon Sep 17 00:00:00 2001 From: Robert Adams Date: Wed, 23 Jan 2013 14:21:52 -0800 Subject: [PATCH 21/24] BulletSim: remove setting of vehicle InterpolationRotationalVelocity. This doesn't seem to help the vehicle stability. Rename vehicle internal variables adding a "V" or "W" so it is clear when coordinates are vehicle or world relative. --- .../Physics/BulletSPlugin/BSDynamics.cs | 66 +++++++++---------- .../Region/Physics/BulletSPlugin/BSPrim.cs | 4 +- 2 files changed, 34 insertions(+), 36 deletions(-) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index dbe44de5f4..fe7891e866 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -690,7 +690,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Bullet does a bunch of smoothing for changing parameters. // Since the vehicle is demanding this setting, we override Bullet's smoothing // by telling Bullet the value was the same last time. - PhysicsScene.PE.SetInterpolationLinearVelocity(Prim.PhysBody, m_knownVelocity); + // PhysicsScene.PE.SetInterpolationLinearVelocity(Prim.PhysBody, m_knownVelocity); } if ((m_knownChanged & m_knownChangedForce) != 0) @@ -702,7 +702,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin if ((m_knownChanged & m_knownChangedRotationalVelocity) != 0) { Prim.ForceRotationalVelocity = m_knownRotationalVelocity; - PhysicsScene.PE.SetInterpolationAngularVelocity(Prim.PhysBody, m_knownRotationalVelocity); + // PhysicsScene.PE.SetInterpolationAngularVelocity(Prim.PhysBody, m_knownRotationalVelocity); } if ((m_knownChanged & m_knownChangedRotationalImpulse) != 0) @@ -963,23 +963,23 @@ namespace OpenSim.Region.Physics.BulletSPlugin { // Step the motor from the current value. Get the correction needed this step. Vector3 currentVel = VehicleVelocity * Quaternion.Inverse(VehicleOrientation); - Vector3 linearMotorCorrection = m_linearMotor.Step(pTimestep, currentVel); + Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVel); // Motor is vehicle coordinates. Rotate it to world coordinates - Vector3 linearMotorVelocity = linearMotorCorrection * VehicleOrientation; + Vector3 linearMotorVelocityW = linearMotorCorrectionV * VehicleOrientation; // If we're a ground vehicle, don't add any upward Z movement if ((m_flags & VehicleFlag.LIMIT_MOTOR_UP) != 0) { - if (linearMotorVelocity.Z > 0f) - linearMotorVelocity.Z = 0f; + if (linearMotorVelocityW.Z > 0f) + linearMotorVelocityW.Z = 0f; } // Add this correction to the velocity to make it faster/slower. - VehicleVelocity += linearMotorVelocity; + VehicleVelocity += linearMotorVelocityW; VDetailLog("{0}, MoveLinear,velocity,vehVel={1},correction={2},force={3}", - Prim.LocalID, VehicleVelocity, linearMotorCorrection, linearMotorVelocity); + Prim.LocalID, VehicleVelocity, linearMotorCorrectionV, linearMotorVelocityW); } public void ComputeLinearTerrainHeightCorrection(float pTimestep) @@ -1123,8 +1123,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin // a downward raycast to find what is below. public void ComputeLinearMotorUp(float pTimestep) { - Vector3 ret = Vector3.Zero; - if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) { // This code tries to decide if the object is not on the ground and then pushing down @@ -1250,8 +1248,8 @@ namespace OpenSim.Region.Physics.BulletSPlugin private void ComputeAngularTurning(float pTimestep) { // The user wants this many radians per second angular change? - Vector3 currentAngular = VehicleRotationalVelocity * Quaternion.Inverse(VehicleOrientation); - Vector3 angularMotorContribution = m_angularMotor.Step(pTimestep, currentAngular); + Vector3 currentAngularV = VehicleRotationalVelocity * Quaternion.Inverse(VehicleOrientation); + Vector3 angularMotorContributionV = m_angularMotor.Step(pTimestep, currentAngularV); // ================================================================== // From http://wiki.secondlife.com/wiki/LlSetVehicleFlags : @@ -1263,12 +1261,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin // is a linear effect. Where should this check go? if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) { - angularMotorContribution.X = 0f; - angularMotorContribution.Y = 0f; + angularMotorContributionV.X = 0f; + angularMotorContributionV.Y = 0f; } - VehicleRotationalVelocity += angularMotorContribution * VehicleOrientation; - VDetailLog("{0}, MoveAngular,angularTurning,angularMotorContrib={1}", Prim.LocalID, angularMotorContribution); + VehicleRotationalVelocity += angularMotorContributionV * VehicleOrientation; + VDetailLog("{0}, MoveAngular,angularTurning,angularMotorContrib={1}", Prim.LocalID, angularMotorContributionV); } // From http://wiki.secondlife.com/wiki/Linden_Vehicle_Tutorial: @@ -1284,7 +1282,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // If vertical attaction timescale is reasonable if (enableAngularVerticalAttraction && m_verticalAttractionTimescale < m_verticalAttractionCutoff) { - Vector3 vertContribution = Vector3.Zero; + Vector3 vertContributionV = Vector3.Zero; // Take a vector pointing up and convert it from world to vehicle relative coords. Vector3 verticalError = Vector3.UnitZ * VehicleOrientation; @@ -1299,26 +1297,26 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Y error means needed rotation around X axis and visa versa. // Since the error goes from zero to one, the asin is the corresponding angle. - vertContribution.X = (float)Math.Asin(verticalError.Y); + vertContributionV.X = (float)Math.Asin(verticalError.Y); // (Tilt forward (positive X) needs to tilt back (rotate negative) around Y axis.) - vertContribution.Y = -(float)Math.Asin(verticalError.X); + vertContributionV.Y = -(float)Math.Asin(verticalError.X); // If verticalError.Z is negative, the vehicle is upside down. Add additional push. if (verticalError.Z < 0f) { - vertContribution.X += PIOverFour; + vertContributionV.X += PIOverFour; // vertContribution.Y -= PIOverFour; } // 'vertContrbution' is now the necessary angular correction to correct tilt in one second. // Correction happens over a number of seconds. - Vector3 unscaledContrib = vertContribution; // DEBUG DEBUG - vertContribution /= m_verticalAttractionTimescale; + Vector3 unscaledContrib = vertContributionV; // DEBUG DEBUG + vertContributionV /= m_verticalAttractionTimescale; - VehicleRotationalVelocity += vertContribution * VehicleOrientation; + VehicleRotationalVelocity += vertContributionV * VehicleOrientation; VDetailLog("{0}, MoveAngular,verticalAttraction,,verticalError={1},unscaled={2},eff={3},ts={4},vertAttr={5}", - Prim.LocalID, verticalError, unscaledContrib, m_verticalAttractionEfficiency, m_verticalAttractionTimescale, vertContribution); + Prim.LocalID, verticalError, unscaledContrib, m_verticalAttractionEfficiency, m_verticalAttractionTimescale, vertContributionV); } } @@ -1336,7 +1334,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin if (enableAngularDeflection && m_angularDeflectionEfficiency != 0 && VehicleForwardSpeed > 0.2) { - Vector3 deflectContribution = Vector3.Zero; + Vector3 deflectContributionV = Vector3.Zero; // The direction the vehicle is moving Vector3 movingDirection = VehicleVelocity; @@ -1363,13 +1361,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin // ret = m_angularDeflectionCorrectionMotor(1f, deflectionError); // Scale the correction by recovery timescale and efficiency - deflectContribution = (-deflectionError) * m_angularDeflectionEfficiency; - deflectContribution /= m_angularDeflectionTimescale; + deflectContributionV = (-deflectionError) * m_angularDeflectionEfficiency; + deflectContributionV /= m_angularDeflectionTimescale; - VehicleRotationalVelocity += deflectContribution * VehicleOrientation; + VehicleRotationalVelocity += deflectContributionV * VehicleOrientation; VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}", - Prim.LocalID, movingDirection, pointingDirection, deflectionError, deflectContribution); + Prim.LocalID, movingDirection, pointingDirection, deflectionError, deflectContributionV); VDetailLog("{0}, MoveAngular,Deflection,fwdSpd={1},defEff={2},defTS={3}", Prim.LocalID, VehicleForwardSpeed, m_angularDeflectionEfficiency, m_angularDeflectionTimescale); } @@ -1410,7 +1408,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin { if (enableAngularBanking && m_bankingEfficiency != 0 && m_verticalAttractionTimescale < m_verticalAttractionCutoff) { - Vector3 bankingContribution = Vector3.Zero; + Vector3 bankingContributionV = Vector3.Zero; // Rotate a UnitZ vector (pointing up) to how the vehicle is oriented. // As the vehicle rolls to the right or left, the Y value will increase from @@ -1428,15 +1426,15 @@ namespace OpenSim.Region.Physics.BulletSPlugin mixedYawAngle = ClampInRange(-20f, mixedYawAngle, 20f); // Build the force vector to change rotation from what it is to what it should be - bankingContribution.Z = -mixedYawAngle; + bankingContributionV.Z = -mixedYawAngle; // Don't do it all at once. - bankingContribution /= m_bankingTimescale; + bankingContributionV /= m_bankingTimescale; - VehicleRotationalVelocity += bankingContribution * VehicleOrientation; + VehicleRotationalVelocity += bankingContributionV * VehicleOrientation; VDetailLog("{0}, MoveAngular,Banking,rollComp={1},speed={2},rollComp={3},yAng={4},mYAng={5},ret={6}", - Prim.LocalID, rollComponents, VehicleForwardSpeed, rollComponents, yawAngle, mixedYawAngle, bankingContribution); + Prim.LocalID, rollComponents, VehicleForwardSpeed, rollComponents, yawAngle, mixedYawAngle, bankingContributionV); } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index 731ab7ba52..f80084a7fd 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -1619,7 +1619,7 @@ public sealed class BSPrim : BSPhysObject // entprop.RotationalVelocity = OMV.Vector3.Zero; } - DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG + // DetailLog("{0},BSPrim.UpdateProperties,entry,entprop={1}", LocalID, entprop); // DEBUG DEBUG // Undo any center-of-mass displacement that might have been done. if (PositionDisplacement != OMV.Vector3.Zero) @@ -1636,7 +1636,7 @@ public sealed class BSPrim : BSPhysObject _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; - DetailLog("{0},BSPrim.UpdateProperties,afterAssign,entprop={1}", LocalID, entprop); // DEBUG DEBUG + // DetailLog("{0},BSPrim.UpdateProperties,afterAssign,entprop={1}", LocalID, entprop); // DEBUG DEBUG // The sanity check can change the velocity and/or position. if (IsPhysical && PositionSanityCheck(true)) From 72dd3633eeb74c64620ffedb1618e732cbbca641 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 23 Jan 2013 23:34:15 +0000 Subject: [PATCH 22/24] Improve logging by making it clearer which script is failing if an assembly fails to load. Moves the noise co-op start/stop debug log messages to only display if xengine debug level >= 1 Logs which stop strategy is being used (abort or co-op) Adjusts some other logging to remove not very useful stuff --- .../Shared/Instance/ScriptInstance.cs | 42 ++++++++++--------- .../ScriptEngine/XEngine/EventManager.cs | 4 +- .../Region/ScriptEngine/XEngine/XEngine.cs | 13 +++--- 3 files changed, 31 insertions(+), 28 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index 4cfcb750a5..5bc585e15f 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -284,9 +284,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance else { m_log.ErrorFormat( - "[SCRIPT INSTANCE]: You must remove all existing script DLLs before using enabling co-op termination" + "[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 all *.dll* files in the relevant bin/ScriptEngines// directory"); + + " or by deleting these files manually.", + ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, assembly); return false; } @@ -324,8 +325,8 @@ 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; } @@ -345,8 +346,8 @@ 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 false; } @@ -401,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 @@ -598,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(); @@ -609,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; } @@ -922,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/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/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 604924bd0e..ad79a9b6dd 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -241,7 +241,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine m_ScriptConfig = configSource.Configs["XEngine"]; m_ConfigSource = configSource; - if (m_ScriptConfig.GetString("ScriptStopStrategy", "abort") == "co-op") + string rawScriptStopStrategy = m_ScriptConfig.GetString("ScriptStopStrategy", "abort"); + + m_log.InfoFormat("[XEngine]: Script stop strategy is {0}", rawScriptStopStrategy); + + if (rawScriptStopStrategy == "co-op") { ScriptClassName = "XEngineScript"; ScriptBaseClassName = typeof(XEngineScriptBase).FullName; @@ -261,15 +265,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine { if (m_ScriptConfig == null) return; + m_ScriptFailCount = 0; m_ScriptErrorMessage = String.Empty; - if (m_ScriptConfig == null) - { -// m_log.ErrorFormat("[XEngine] No script configuration found. Scripts disabled"); - return; - } - m_Enabled = m_ScriptConfig.GetBoolean("Enabled", true); if (!m_Enabled) From 8a22ac3f94a3b8275d794721e0daca5c58e952a2 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 23 Jan 2013 23:38:08 +0000 Subject: [PATCH 23/24] Pass narrower WaitHandle rather than EventWaitHandle as co-op termination wait handle to script APIs. APIs don't need to reference any methods on EventWaitHandle --- OpenSim/Region/ScriptEngine/Interfaces/IScriptApi.cs | 2 +- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 4 ++-- .../Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs | 2 +- .../Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs | 2 +- .../Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) 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/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index cee10a8e6e..89ea4e93e3 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; 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 25635ff767..f2f8fd65ab 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; From c51cae8fe81e26e7bb1cb5de1e3fdc505c01fb0a Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 23 Jan 2013 23:57:09 +0000 Subject: [PATCH 24/24] Add information on ScriptStopStrategy to [XEngine] in OpenSimDefaults.ini and OpenSim.ini.example. Default remains abort. This setting controls whether scripts are stopped by aborting their threads externally (abort) or by co-operative checks from the compiled script (co-op) co-op should be more stable but this option is experimental. If moving from co-op to abort, existing script DLLs will need to be recompiled. This currently can only be done manually, either by setting DeleteScriptsOnStartup = true for one run or by deleting the script DLL* files in bin/ScriptEngines// One can move from co-op back to abort without recompilation, but reverting back to co-op again will need script recompile --- bin/OpenSim.ini.example | 24 +++++++++++++++++------- bin/OpenSimDefaults.ini | 20 ++++++++++++++------ 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 658b993488..0fe44e954d 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -749,13 +749,6 @@ ;; The trade-off may be increased memory usage by the script engine. ; ThreadStackSize = 262144 - ;# {DeleteScriptsOnStartup} {} {Delete previously compiled script DLLs on startup?} (true false) true - ;; Controls whether previously compiled scripts DLLs are deleted on sim restart. If you set this to false - ;; then startup will be considerably faster since scripts won't need to be recompiled. However, then it becomes your responsibility to delete the - ;; compiled scripts if you're recompiling OpenSim from source code and internal interfaces used - ;; by scripts have changed. - ; DeleteScriptsOnStartup = true - ;; Set this to true (the default) to load each script into a separate ;; AppDomain. ;; @@ -768,6 +761,23 @@ ;; Some Windows users have also reported script loading problems when AppDomainLoading = false ; AppDomainLoading = true + ;; Controls whether scripts are stopped by aborting their threads externally (abort) or by co-operative checks from the compiled script (co-op) + ;; co-op will be more stable but this option is currently experimental. + ;; If moving from co-op to abort, existing script DLLs will need to be recompiled. + ;; This currently can only be done manually, either by setting DeleteScriptsOnStartup = true for one run + ;; or by deleting the script DLL* files in bin/ScriptEngines// + ;; One can move from co-op back to abort without recompilation, but reverting back to co-op again will need script recompile + ;; Current valid values are "abort" and "co-op" + ; ScriptStopStrategy = abort + + + ;# {DeleteScriptsOnStartup} {} {Delete previously compiled script DLLs on startup?} (true false) true + ;; Controls whether previously compiled scripts DLLs are deleted on sim restart. If you set this to false + ;; then startup will be considerably faster since scripts won't need to be recompiled. However, then it becomes your responsibility to delete the + ;; compiled scripts if you're recompiling OpenSim from source code and internal interfaces used + ;; by scripts have changed. + ; DeleteScriptsOnStartup = true + ;# {DefaultCompileLanguage} {Enabled:true} {Default script language?} {lsl vb cs} lsl ;; Default language for scripts ; DefaultCompileLanguage = "lsl" diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index 45c3d401c9..391fb0cab2 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -1290,6 +1290,20 @@ ; script assemblies AppDomainLoading = true + ; Controls whether previously compiled scripts DLLs are deleted on sim restart. If you set this to false + ; then startup will be considerably faster since scripts won't need to be recompiled. However, then it becomes your responsibility to delete the + ; compiled scripts if you're recompiling OpenSim from source code and internal interfaces used + ; by scripts have changed. + ; DeleteScriptsOnStartup = false + + ; Controls whether scripts are stopped by aborting their threads externally (abort) or by co-operative checks from the compiled script (co-op) + ; co-op will be more stable but this option is currently experimental. + ; If moving from co-op to abort, existing script DLLs will need to be recompiled. + ; This currently can only be done manually, either by setting DeleteScriptsOnStartup = true for one run + ; or by deleting the script DLL* files in bin/ScriptEngines// + ; One can move from co-op back to abort without recompilation, but reverting back to co-op again will need script recompile + ScriptStopStrategy = abort + ; Rate to poll for asynchronous command replies (ms) ; currently unused ;AsyncLLCommandLoopms = 50 @@ -1391,12 +1405,6 @@ ;; Path to script assemblies ; ScriptEnginesPath = "ScriptEngines" - ; Controls whether previously compiled scripts DLLs are deleted on sim restart. If you set this to false - ; then startup will be considerably faster since scripts won't need to be recompiled. However, then it becomes your responsibility to delete the - ; compiled scripts if you're recompiling OpenSim from source code and internal interfaces used - ; by scripts have changed. - ; DeleteScriptsOnStartup = false - [Concierge] ; Enable concierge module