Merge branch 'master' of ssh://opensimulator.org/var/git/opensim

user_profiles
Robert Adams 2013-01-23 16:23:11 -08:00
commit 5b334079e0
17 changed files with 674 additions and 146 deletions

View File

@ -46,6 +46,6 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
/// <param name='item'>/param> /// <param name='item'>/param>
/// <param name='coopSleepHandle'>/param> /// <param name='coopSleepHandle'>/param>
void Initialize( void Initialize(
IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, EventWaitHandle coopSleepHandle); IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle);
} }
} }

View File

@ -25,16 +25,17 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using log4net;
using System; using System;
using OpenSim.Region.ScriptEngine.Shared; using System.Reflection;
using OpenSim.Framework;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenMetaverse;
using Nini.Config;
using OpenSim.Region.ScriptEngine.Interfaces; using OpenSim.Region.ScriptEngine.Interfaces;
using OpenSim.Region.ScriptEngine.Shared;
using Amib.Threading; using Amib.Threading;
using OpenSim.Framework; using log4net;
using Nini.Config;
using OpenMetaverse;
namespace OpenSim.Region.ScriptEngine.Interfaces namespace OpenSim.Region.ScriptEngine.Interfaces
{ {
@ -76,6 +77,38 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
IConfigSource ConfigSource { get; } IConfigSource ConfigSource { get; }
string ScriptEngineName { get; } string ScriptEngineName { get; }
string ScriptEnginePath { get; } string ScriptEnginePath { get; }
/// <summary>
/// Return the name of the class that will be used for all running scripts.
/// </summary>
/// <remarks>
/// Each class goes in its own assembly so we don't need to otherwise distinguish the class name.
/// </remarks>
string ScriptClassName { get; }
/// <summary>
/// Return the name of the base class that will be used for all running scripts.
/// </summary>
string ScriptBaseClassName { get; }
/// <summary>
/// Assemblies that need to be referenced when compiling scripts.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
string[] ScriptReferencedAssemblies { get; }
/// <summary>
/// Parameters for the generated script's constructor.
/// </summary>
/// <remarks>
/// Can be null if there are no parameters
/// </remarks>
ParameterInfo[] ScriptBaseClassParameters { get; }
IScriptApi GetApi(UUID itemID, string name); IScriptApi GetApi(UUID itemID, string name);
} }
} }

View File

@ -91,7 +91,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
/// Used for script sleeps when we are using co-operative script termination. /// Used for script sleeps when we are using co-operative script termination.
/// </summary> /// </summary>
/// <remarks>null if co-operative script termination is not active</remarks> /// <remarks>null if co-operative script termination is not active</remarks>
EventWaitHandle m_coopSleepHandle; WaitHandle m_coopSleepHandle;
/// <summary> /// <summary>
/// The item that hosts this script /// The item that hosts this script
@ -118,7 +118,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
protected ISoundModule m_SoundModule = null; protected ISoundModule m_SoundModule = null;
public void Initialize( public void Initialize(
IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, EventWaitHandle coopSleepHandle) IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle)
{ {
m_ScriptEngine = scriptEngine; m_ScriptEngine = scriptEngine;
m_host = host; m_host = host;
@ -192,7 +192,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
if (m_coopSleepHandle == null) if (m_coopSleepHandle == null)
System.Threading.Thread.Sleep(delay); System.Threading.Thread.Sleep(delay);
else if (m_coopSleepHandle.WaitOne(delay)) else
CheckForCoopTermination(delay);
}
/// <summary>
/// Check for co-operative termination.
/// </summary>
/// <param name='delay'>If called with 0, then just the check is performed with no wait.</param>
protected virtual void CheckForCoopTermination(int delay)
{
if (m_coopSleepHandle.WaitOne(delay))
throw new ScriptCoopStopException(); throw new ScriptCoopStopException();
} }

View File

@ -63,7 +63,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
internal IScriptModuleComms m_comms = null; internal IScriptModuleComms m_comms = null;
public void Initialize( public void Initialize(
IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, EventWaitHandle coopSleepHandle) IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle)
{ {
m_ScriptEngine = scriptEngine; m_ScriptEngine = scriptEngine;
m_host = host; m_host = host;

View File

@ -63,7 +63,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
internal IScriptModuleComms m_comms = null; internal IScriptModuleComms m_comms = null;
public void Initialize( public void Initialize(
IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, EventWaitHandle coopSleepHandle) IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle)
{ {
m_ScriptEngine = scriptEngine; m_ScriptEngine = scriptEngine;
m_host = host; m_host = host;

View File

@ -143,7 +143,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
protected IUrlModule m_UrlModule = null; protected IUrlModule m_UrlModule = null;
public void Initialize( public void Initialize(
IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, EventWaitHandle coopSleepHandle) IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle)
{ {
m_ScriptEngine = scriptEngine; m_ScriptEngine = scriptEngine;
m_host = host; m_host = host;

View File

@ -49,6 +49,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
private List<string> m_warnings = new List<string>(); private List<string> m_warnings = new List<string>();
private IScriptModuleComms m_comms = null; private IScriptModuleComms m_comms = null;
private bool m_insertCoopTerminationChecks;
private static string m_coopTerminationCheck = "opensim_reserved_CheckForCoopTermination();";
/// <summary>
/// Keep a record of the previous node when we do the parsing.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
// private SYMBOL m_previousNode;
/// <summary> /// <summary>
/// Creates an 'empty' CSCodeGenerator instance. /// Creates an 'empty' CSCodeGenerator instance.
/// </summary> /// </summary>
@ -58,9 +70,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
ResetCounters(); ResetCounters();
} }
public CSCodeGenerator(IScriptModuleComms comms) public CSCodeGenerator(IScriptModuleComms comms, bool insertCoopTerminationChecks)
{ {
m_comms = comms; m_comms = comms;
m_insertCoopTerminationChecks = insertCoopTerminationChecks;
ResetCounters(); ResetCounters();
} }
@ -155,7 +168,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
// here's the payload // here's the payload
retstr += GenerateLine(); retstr += GenerateLine();
foreach (SYMBOL s in m_astRoot.kids) foreach (SYMBOL s in m_astRoot.kids)
retstr += GenerateNode(s); retstr += GenerateNode(m_astRoot, s);
// close braces! // close braces!
m_braceCount--; m_braceCount--;
@ -191,9 +204,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
/// Recursively called to generate each type of node. Will generate this /// Recursively called to generate each type of node. Will generate this
/// node, then all it's children. /// node, then all it's children.
/// </summary> /// </summary>
/// <param name="previousSymbol">The parent node.</param>
/// <param name="s">The current node to generate code for.</param> /// <param name="s">The current node to generate code for.</param>
/// <returns>String containing C# code for SYMBOL s.</returns> /// <returns>String containing C# code for SYMBOL s.</returns>
private string GenerateNode(SYMBOL s) private string GenerateNode(SYMBOL previousSymbol, SYMBOL s)
{ {
string retstr = String.Empty; string retstr = String.Empty;
@ -207,11 +221,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
else if (s is State) else if (s is State)
retstr += GenerateState((State) s); retstr += GenerateState((State) s);
else if (s is CompoundStatement) else if (s is CompoundStatement)
retstr += GenerateCompoundStatement((CompoundStatement) s); retstr += GenerateCompoundStatement(previousSymbol, (CompoundStatement) s);
else if (s is Declaration) else if (s is Declaration)
retstr += GenerateDeclaration((Declaration) s); retstr += GenerateDeclaration((Declaration) s);
else if (s is Statement) else if (s is Statement)
retstr += GenerateStatement((Statement) s); retstr += GenerateStatement(previousSymbol, (Statement) s);
else if (s is ReturnStatement) else if (s is ReturnStatement)
retstr += GenerateReturnStatement((ReturnStatement) s); retstr += GenerateReturnStatement((ReturnStatement) s);
else if (s is JumpLabel) else if (s is JumpLabel)
@ -261,7 +275,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
else else
{ {
foreach (SYMBOL kid in s.kids) foreach (SYMBOL kid in s.kids)
retstr += GenerateNode(kid); retstr += GenerateNode(s, kid);
} }
return retstr; return retstr;
@ -295,7 +309,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
retstr += GenerateLine(")"); retstr += GenerateLine(")");
foreach (SYMBOL kid in remainingKids) foreach (SYMBOL kid in remainingKids)
retstr += GenerateNode(kid); retstr += GenerateNode(gf, kid);
return retstr; return retstr;
} }
@ -312,7 +326,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
foreach (SYMBOL s in gv.kids) foreach (SYMBOL s in gv.kids)
{ {
retstr += Indent(); retstr += Indent();
retstr += GenerateNode(s); retstr += GenerateNode(gv, s);
retstr += GenerateLine(";"); retstr += GenerateLine(";");
} }
@ -365,7 +379,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
retstr += GenerateLine(")"); retstr += GenerateLine(")");
foreach (SYMBOL kid in remainingKids) foreach (SYMBOL kid in remainingKids)
retstr += GenerateNode(kid); retstr += GenerateNode(se, kid);
return retstr; return retstr;
} }
@ -404,7 +418,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
foreach (SYMBOL s in al.kids) foreach (SYMBOL s in al.kids)
{ {
retstr += GenerateNode(s); retstr += GenerateNode(al, s);
if (0 < comma--) if (0 < comma--)
retstr += Generate(", "); retstr += Generate(", ");
} }
@ -417,7 +431,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
/// </summary> /// </summary>
/// <param name="cs">The CompoundStatement node.</param> /// <param name="cs">The CompoundStatement node.</param>
/// <returns>String containing C# code for CompoundStatement cs.</returns> /// <returns>String containing C# code for CompoundStatement cs.</returns>
private string GenerateCompoundStatement(CompoundStatement cs) private string GenerateCompoundStatement(SYMBOL previousSymbol, CompoundStatement cs)
{ {
string retstr = String.Empty; string retstr = String.Empty;
@ -425,8 +439,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
retstr += GenerateIndentedLine("{"); retstr += GenerateIndentedLine("{");
m_braceCount++; m_braceCount++;
if (m_insertCoopTerminationChecks)
{
// We have to check in event functions as well because the user can manually call these.
if (previousSymbol is GlobalFunctionDefinition
|| previousSymbol is WhileStatement
|| previousSymbol is DoWhileStatement
|| previousSymbol is ForLoop
|| previousSymbol is StateEvent)
retstr += GenerateIndentedLine(m_coopTerminationCheck);
}
foreach (SYMBOL kid in cs.kids) foreach (SYMBOL kid in cs.kids)
retstr += GenerateNode(kid); retstr += GenerateNode(cs, kid);
// closing brace // closing brace
m_braceCount--; m_braceCount--;
@ -450,13 +475,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
/// </summary> /// </summary>
/// <param name="s">The Statement node.</param> /// <param name="s">The Statement node.</param>
/// <returns>String containing C# code for Statement s.</returns> /// <returns>String containing C# code for Statement s.</returns>
private string GenerateStatement(Statement s) private string GenerateStatement(SYMBOL previousSymbol, Statement s)
{ {
string retstr = String.Empty; string retstr = String.Empty;
bool printSemicolon = true; bool printSemicolon = true;
retstr += Indent(); 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) if (0 < s.kids.Count)
{ {
// Jump label prints its own colon, we don't need a semicolon. // Jump label prints its own colon, we don't need a semicolon.
@ -466,7 +502,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
// (MONO) error. // (MONO) error.
if (!(s.kids.Top is IdentExpression && 1 == s.kids.Count)) if (!(s.kids.Top is IdentExpression && 1 == s.kids.Count))
foreach (SYMBOL kid in s.kids) foreach (SYMBOL kid in s.kids)
retstr += GenerateNode(kid); retstr += GenerateNode(s, kid);
} }
if (printSemicolon) if (printSemicolon)
@ -487,10 +523,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
List<string> identifiers = new List<string>(); List<string> identifiers = new List<string>();
checkForMultipleAssignments(identifiers, a); checkForMultipleAssignments(identifiers, a);
retstr += GenerateNode((SYMBOL) a.kids.Pop()); retstr += GenerateNode(a, (SYMBOL) a.kids.Pop());
retstr += Generate(String.Format(" {0} ", a.AssignmentType), a); retstr += Generate(String.Format(" {0} ", a.AssignmentType), a);
foreach (SYMBOL kid in a.kids) foreach (SYMBOL kid in a.kids)
retstr += GenerateNode(kid); retstr += GenerateNode(a, kid);
return retstr; return retstr;
} }
@ -563,7 +599,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
retstr += Generate("return ", rs); retstr += Generate("return ", rs);
foreach (SYMBOL kid in rs.kids) foreach (SYMBOL kid in rs.kids)
retstr += GenerateNode(kid); retstr += GenerateNode(rs, kid);
return retstr; return retstr;
} }
@ -575,7 +611,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
/// <returns>String containing C# code for JumpLabel jl.</returns> /// <returns>String containing C# code for JumpLabel jl.</returns>
private string GenerateJumpLabel(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;
} }
/// <summary> /// <summary>
@ -598,14 +641,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
string retstr = String.Empty; string retstr = String.Empty;
retstr += GenerateIndented("if (", ifs); retstr += GenerateIndented("if (", ifs);
retstr += GenerateNode((SYMBOL) ifs.kids.Pop()); retstr += GenerateNode(ifs, (SYMBOL) ifs.kids.Pop());
retstr += GenerateLine(")"); retstr += GenerateLine(")");
// CompoundStatement handles indentation itself but we need to do it // CompoundStatement handles indentation itself but we need to do it
// otherwise. // otherwise.
bool indentHere = ifs.kids.Top is Statement; bool indentHere = ifs.kids.Top is Statement;
if (indentHere) m_braceCount++; if (indentHere) m_braceCount++;
retstr += GenerateNode((SYMBOL) ifs.kids.Pop()); retstr += GenerateNode(ifs, (SYMBOL) ifs.kids.Pop());
if (indentHere) m_braceCount--; if (indentHere) m_braceCount--;
if (0 < ifs.kids.Count) // do it again for an else 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; indentHere = ifs.kids.Top is Statement;
if (indentHere) m_braceCount++; if (indentHere) m_braceCount++;
retstr += GenerateNode((SYMBOL) ifs.kids.Pop()); retstr += GenerateNode(ifs, (SYMBOL) ifs.kids.Pop());
if (indentHere) m_braceCount--; if (indentHere) m_braceCount--;
} }
@ -641,14 +684,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
string retstr = String.Empty; string retstr = String.Empty;
retstr += GenerateIndented("while (", ws); retstr += GenerateIndented("while (", ws);
retstr += GenerateNode((SYMBOL) ws.kids.Pop()); retstr += GenerateNode(ws, (SYMBOL) ws.kids.Pop());
retstr += GenerateLine(")"); retstr += GenerateLine(")");
// CompoundStatement handles indentation itself but we need to do it // CompoundStatement handles indentation itself but we need to do it
// otherwise. // otherwise.
bool indentHere = ws.kids.Top is Statement; bool indentHere = ws.kids.Top is Statement;
if (indentHere) m_braceCount++; if (indentHere) m_braceCount++;
retstr += GenerateNode((SYMBOL) ws.kids.Pop()); retstr += GenerateNode(ws, (SYMBOL) ws.kids.Pop());
if (indentHere) m_braceCount--; if (indentHere) m_braceCount--;
return retstr; return retstr;
@ -669,11 +712,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
// otherwise. // otherwise.
bool indentHere = dws.kids.Top is Statement; bool indentHere = dws.kids.Top is Statement;
if (indentHere) m_braceCount++; if (indentHere) m_braceCount++;
retstr += GenerateNode((SYMBOL) dws.kids.Pop()); retstr += GenerateNode(dws, (SYMBOL) dws.kids.Pop());
if (indentHere) m_braceCount--; if (indentHere) m_braceCount--;
retstr += GenerateIndented("while (", dws); retstr += GenerateIndented("while (", dws);
retstr += GenerateNode((SYMBOL) dws.kids.Pop()); retstr += GenerateNode(dws, (SYMBOL) dws.kids.Pop());
retstr += GenerateLine(");"); retstr += GenerateLine(");");
return retstr; return retstr;
@ -702,7 +745,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
retstr += Generate("; "); retstr += Generate("; ");
// for (x = 0; x < 10; x++) // for (x = 0; x < 10; x++)
// ^^^^^^ // ^^^^^^
retstr += GenerateNode((SYMBOL) fl.kids.Pop()); retstr += GenerateNode(fl, (SYMBOL) fl.kids.Pop());
retstr += Generate("; "); retstr += Generate("; ");
// for (x = 0; x < 10; x++) // for (x = 0; x < 10; x++)
// ^^^ // ^^^
@ -713,7 +756,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
// otherwise. // otherwise.
bool indentHere = fl.kids.Top is Statement; bool indentHere = fl.kids.Top is Statement;
if (indentHere) m_braceCount++; if (indentHere) m_braceCount++;
retstr += GenerateNode((SYMBOL) fl.kids.Pop()); retstr += GenerateNode(fl, (SYMBOL) fl.kids.Pop());
if (indentHere) m_braceCount--; if (indentHere) m_braceCount--;
return retstr; return retstr;
@ -758,7 +801,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
while (s is ParenthesisExpression) while (s is ParenthesisExpression)
s = (SYMBOL)s.kids.Pop(); s = (SYMBOL)s.kids.Pop();
retstr += GenerateNode(s); retstr += GenerateNode(fls, s);
if (0 < comma--) if (0 < comma--)
retstr += Generate(", "); retstr += Generate(", ");
} }
@ -779,20 +822,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
{ {
// special case handling for logical and/or, see Mantis 3174 // special case handling for logical and/or, see Mantis 3174
retstr += "((bool)("; retstr += "((bool)(";
retstr += GenerateNode((SYMBOL)be.kids.Pop()); retstr += GenerateNode(be, (SYMBOL)be.kids.Pop());
retstr += "))"; retstr += "))";
retstr += Generate(String.Format(" {0} ", be.ExpressionSymbol.Substring(0,1)), be); retstr += Generate(String.Format(" {0} ", be.ExpressionSymbol.Substring(0,1)), be);
retstr += "((bool)("; retstr += "((bool)(";
foreach (SYMBOL kid in be.kids) foreach (SYMBOL kid in be.kids)
retstr += GenerateNode(kid); retstr += GenerateNode(be, kid);
retstr += "))"; retstr += "))";
} }
else else
{ {
retstr += GenerateNode((SYMBOL)be.kids.Pop()); retstr += GenerateNode(be, (SYMBOL)be.kids.Pop());
retstr += Generate(String.Format(" {0} ", be.ExpressionSymbol), be); retstr += Generate(String.Format(" {0} ", be.ExpressionSymbol), be);
foreach (SYMBOL kid in be.kids) foreach (SYMBOL kid in be.kids)
retstr += GenerateNode(kid); retstr += GenerateNode(be, kid);
} }
return retstr; return retstr;
@ -808,7 +851,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
string retstr = String.Empty; string retstr = String.Empty;
retstr += Generate(ue.UnarySymbol, ue); retstr += Generate(ue.UnarySymbol, ue);
retstr += GenerateNode((SYMBOL) ue.kids.Pop()); retstr += GenerateNode(ue, (SYMBOL) ue.kids.Pop());
return retstr; return retstr;
} }
@ -824,7 +867,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
retstr += Generate("("); retstr += Generate("(");
foreach (SYMBOL kid in pe.kids) foreach (SYMBOL kid in pe.kids)
retstr += GenerateNode(kid); retstr += GenerateNode(pe, kid);
retstr += Generate(")"); retstr += Generate(")");
return retstr; return retstr;
@ -861,7 +904,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
// we wrap all typecasted statements in parentheses // we wrap all typecasted statements in parentheses
retstr += Generate(String.Format("({0}) (", te.TypecastType), te); retstr += Generate(String.Format("({0}) (", te.TypecastType), te);
retstr += GenerateNode((SYMBOL) te.kids.Pop()); retstr += GenerateNode(te, (SYMBOL) te.kids.Pop());
retstr += Generate(")"); retstr += Generate(")");
return retstr; return retstr;
@ -931,7 +974,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
} }
foreach (SYMBOL kid in fc.kids) foreach (SYMBOL kid in fc.kids)
retstr += GenerateNode(kid); retstr += GenerateNode(fc, kid);
retstr += Generate(")"); retstr += Generate(")");
@ -980,11 +1023,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
string retstr = String.Empty; string retstr = String.Empty;
retstr += Generate(String.Format("new {0}(", vc.Type), vc); 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 += Generate(", ");
retstr += GenerateNode((SYMBOL) vc.kids.Pop()); retstr += GenerateNode(vc, (SYMBOL) vc.kids.Pop());
retstr += Generate(", "); retstr += Generate(", ");
retstr += GenerateNode((SYMBOL) vc.kids.Pop()); retstr += GenerateNode(vc, (SYMBOL) vc.kids.Pop());
retstr += Generate(")"); retstr += Generate(")");
return retstr; return retstr;
@ -1000,13 +1043,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
string retstr = String.Empty; string retstr = String.Empty;
retstr += Generate(String.Format("new {0}(", rc.Type), rc); 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 += Generate(", ");
retstr += GenerateNode((SYMBOL) rc.kids.Pop()); retstr += GenerateNode(rc, (SYMBOL) rc.kids.Pop());
retstr += Generate(", "); retstr += Generate(", ");
retstr += GenerateNode((SYMBOL) rc.kids.Pop()); retstr += GenerateNode(rc, (SYMBOL) rc.kids.Pop());
retstr += Generate(", "); retstr += Generate(", ");
retstr += GenerateNode((SYMBOL) rc.kids.Pop()); retstr += GenerateNode(rc, (SYMBOL) rc.kids.Pop());
retstr += Generate(")"); retstr += Generate(")");
return retstr; return retstr;
@ -1024,7 +1067,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
retstr += Generate(String.Format("new {0}(", lc.Type), lc); retstr += Generate(String.Format("new {0}(", lc.Type), lc);
foreach (SYMBOL kid in lc.kids) foreach (SYMBOL kid in lc.kids)
retstr += GenerateNode(kid); retstr += GenerateNode(lc, kid);
retstr += Generate(")"); retstr += Generate(")");

View File

@ -31,6 +31,7 @@ using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Reflection; using System.Reflection;
using System.IO; using System.IO;
using System.Linq;
using System.Text; using System.Text;
using Microsoft.CSharp; using Microsoft.CSharp;
//using Microsoft.JScript; //using Microsoft.JScript;
@ -72,6 +73,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
private bool CompileWithDebugInformation; private bool CompileWithDebugInformation;
private Dictionary<string, bool> AllowedCompilers = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase); private Dictionary<string, bool> AllowedCompilers = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
private Dictionary<string, enumCompileType> LanguageMapping = new Dictionary<string, enumCompileType>(StringComparer.CurrentCultureIgnoreCase); private Dictionary<string, enumCompileType> LanguageMapping = new Dictionary<string, enumCompileType>(StringComparer.CurrentCultureIgnoreCase);
private bool m_insertCoopTerminationCalls;
private string FilePrefix; private string FilePrefix;
private string ScriptEnginesPath = null; private string ScriptEnginesPath = null;
@ -95,20 +97,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
private Dictionary<string, Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>> m_lineMaps = private Dictionary<string, Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>> m_lineMaps =
new Dictionary<string, Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>>(); new Dictionary<string, Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>>>();
public bool in_startup = true;
public Compiler(IScriptEngine scriptEngine) public Compiler(IScriptEngine scriptEngine)
{ {
m_scriptEngine = scriptEngine;; m_scriptEngine = scriptEngine;
ScriptEnginesPath = scriptEngine.ScriptEnginePath; ScriptEnginesPath = scriptEngine.ScriptEnginePath;
ReadConfig(); ReadConfig();
} }
public bool in_startup = true;
public void ReadConfig() public void ReadConfig()
{ {
// Get some config // Get some config
WriteScriptSourceToDebugFile = m_scriptEngine.Config.GetBoolean("WriteScriptSourceToDebugFile", false); WriteScriptSourceToDebugFile = m_scriptEngine.Config.GetBoolean("WriteScriptSourceToDebugFile", false);
CompileWithDebugInformation = m_scriptEngine.Config.GetBoolean("CompileWithDebugInformation", true); CompileWithDebugInformation = m_scriptEngine.Config.GetBoolean("CompileWithDebugInformation", true);
bool DeleteScriptsOnStartup = m_scriptEngine.Config.GetBoolean("DeleteScriptsOnStartup", 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: // Get file prefix from scriptengine name and make it file system safe:
FilePrefix = "CommonCompiler"; FilePrefix = "CommonCompiler";
@ -386,7 +390,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
if (language == enumCompileType.lsl) if (language == enumCompileType.lsl)
{ {
// Its LSL, convert it to C# // 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); compileScript = LSL_Converter.Convert(Script);
// copy converter warnings into our warnings. // copy converter warnings into our warnings.
@ -411,16 +415,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
{ {
case enumCompileType.cs: case enumCompileType.cs:
case enumCompileType.lsl: case enumCompileType.lsl:
compileScript = CreateCSCompilerScript(compileScript); compileScript = CreateCSCompilerScript(
compileScript,
m_scriptEngine.ScriptClassName,
m_scriptEngine.ScriptBaseClassName,
m_scriptEngine.ScriptBaseClassParameters);
break; break;
case enumCompileType.vb: case enumCompileType.vb:
compileScript = CreateVBCompilerScript(compileScript); compileScript = CreateVBCompilerScript(
compileScript, m_scriptEngine.ScriptClassName, m_scriptEngine.ScriptBaseClassName);
break; break;
// case enumCompileType.js: // case enumCompileType.js:
// compileScript = CreateJSCompilerScript(compileScript); // compileScript = CreateJSCompilerScript(compileScript, m_scriptEngine.ScriptBaseClassName);
// break; // break;
case enumCompileType.yp: case enumCompileType.yp:
compileScript = CreateYPCompilerScript(compileScript); compileScript = CreateYPCompilerScript(
compileScript, m_scriptEngine.ScriptClassName,m_scriptEngine.ScriptBaseClassName);
break; break;
} }
@ -451,43 +461,60 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
// return compileScript; // return compileScript;
// } // }
private static string CreateCSCompilerScript(string compileScript) private static string CreateCSCompilerScript(
string compileScript, string className, string baseClassName, ParameterInfo[] constructorParameters)
{ {
compileScript = String.Empty + compileScript = string.Format(
"using OpenSim.Region.ScriptEngine.Shared; using System.Collections.Generic;\r\n" + @"using OpenSim.Region.ScriptEngine.Shared;
String.Empty + "namespace SecondLife { " + using System.Collections.Generic;
String.Empty + "public class Script : OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass { \r\n" +
@"public Script() { } " + namespace SecondLife
compileScript + {{
"} }\r\n"; public class {0} : {1}
{{
public {0}({2}) : base({3}) {{}}
{4}
}}
}}",
className,
baseClassName,
constructorParameters != null
? string.Join(", ", Array.ConvertAll<ParameterInfo, string>(constructorParameters, pi => pi.ToString()))
: "",
constructorParameters != null
? string.Join(", ", Array.ConvertAll<ParameterInfo, string>(constructorParameters, pi => pi.Name))
: "",
compileScript);
return compileScript; return compileScript;
} }
private static string CreateYPCompilerScript(string compileScript) private static string CreateYPCompilerScript(string compileScript, string className, string baseClassName)
{ {
compileScript = String.Empty + compileScript = String.Empty +
"using OpenSim.Region.ScriptEngine.Shared.YieldProlog; " + "using OpenSim.Region.ScriptEngine.Shared.YieldProlog; " +
"using OpenSim.Region.ScriptEngine.Shared; using System.Collections.Generic;\r\n" + "using OpenSim.Region.ScriptEngine.Shared; using System.Collections.Generic;\r\n" +
String.Empty + "namespace SecondLife { " + String.Empty + "namespace SecondLife { " +
String.Empty + "public class Script : OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass { \r\n" + String.Empty + "public class " + className + " : " + baseClassName + " { \r\n" +
//@"public Script() { } " + //@"public Script() { } " +
@"static OpenSim.Region.ScriptEngine.Shared.YieldProlog.YP YP=null; " + @"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 + compileScript +
"} }\r\n"; "} }\r\n";
return compileScript; return compileScript;
} }
private static string CreateVBCompilerScript(string compileScript) private static string CreateVBCompilerScript(string compileScript, string className, string baseClassName)
{ {
compileScript = String.Empty + compileScript = String.Empty +
"Imports OpenSim.Region.ScriptEngine.Shared: Imports System.Collections.Generic: " + "Imports OpenSim.Region.ScriptEngine.Shared: Imports System.Collections.Generic: " +
String.Empty + "NameSpace SecondLife:" + String.Empty + "NameSpace SecondLife:" +
String.Empty + "Public Class Script: Inherits OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass: " + String.Empty + "Public Class " + className + ": Inherits " + baseClassName +
"\r\nPublic Sub New()\r\nEnd Sub: " + "\r\nPublic Sub New()\r\nEnd Sub: " +
compileScript + compileScript +
":End Class :End Namespace\r\n"; ":End Class :End Namespace\r\n";
return compileScript; return compileScript;
} }
@ -549,6 +576,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,
"OpenMetaverseTypes.dll")); "OpenMetaverseTypes.dll"));
if (m_scriptEngine.ScriptReferencedAssemblies != null)
Array.ForEach<string>(
m_scriptEngine.ScriptReferencedAssemblies,
a => parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, a)));
if (lang == enumCompileType.yp) if (lang == enumCompileType.yp)
{ {
parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, parameters.ReferencedAssemblies.Add(Path.Combine(rootPath,

View File

@ -251,7 +251,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
/// <param name='dom'></param> /// <param name='dom'></param>
/// <param name='assembly'></param> /// <param name='assembly'></param>
/// <param name='stateSource'></param> /// <param name='stateSource'></param>
public void Load(AppDomain dom, string assembly, StateSource stateSource) /// <returns>false if load failed, true if suceeded</returns>
public bool Load(AppDomain dom, string assembly, StateSource stateSource)
{ {
m_Assembly = assembly; m_Assembly = assembly;
m_stateSource = stateSource; m_stateSource = stateSource;
@ -266,14 +267,56 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
try try
{ {
if (dom != System.AppDomain.CurrentDomain) object[] constructorParams;
m_Script = (IScript)dom.CreateInstanceAndUnwrap(
Path.GetFileNameWithoutExtension(assembly), Assembly scriptAssembly = dom.Load(Path.GetFileNameWithoutExtension(assembly));
"SecondLife.Script"); 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 else
m_Script = (IScript)Assembly.Load( {
Path.GetFileNameWithoutExtension(assembly)).CreateInstance( m_log.ErrorFormat(
"SecondLife.Script"); "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. You must remove all existing {6}* script DLL files before using enabling co-op termination"
+ ", either by setting DeleteScriptsOnStartup = true in [XEngine] for one run"
+ " or by deleting these files manually.",
ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, assembly);
return false;
}
// m_log.DebugFormat(
// "[SCRIPT INSTANCE]: Looking to load {0} from assembly {1} in {2}",
// scriptType.FullName, Path.GetFileNameWithoutExtension(assembly), Engine.World.Name);
if (dom != System.AppDomain.CurrentDomain)
m_Script
= (IScript)dom.CreateInstanceAndUnwrap(
Path.GetFileNameWithoutExtension(assembly),
scriptType.FullName,
false,
BindingFlags.Default,
null,
constructorParams,
null,
null);
else
m_Script
= (IScript)scriptAssembly.CreateInstance(
scriptType.FullName,
false,
BindingFlags.Default,
null,
constructorParams,
null,
null);
//ILease lease = (ILease)RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass); //ILease lease = (ILease)RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass);
//RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass); //RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass);
@ -282,8 +325,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
catch (Exception e) catch (Exception e)
{ {
m_log.ErrorFormat( m_log.ErrorFormat(
"[SCRIPT INSTANCE]: Error loading assembly {0}. Exception {1}{2}", "[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}",
assembly, e.Message, e.StackTrace); ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, assembly, e.Message, e.StackTrace);
return false;
} }
try try
@ -301,10 +346,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
catch (Exception e) catch (Exception e)
{ {
m_log.ErrorFormat( m_log.ErrorFormat(
"[SCRIPT INSTANCE]: Error loading script instance from assembly {0}. Exception {1}{2}", "[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}",
assembly, e.Message, e.StackTrace); ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, e.Message, e.StackTrace);
return; return false;
} }
m_SaveState = true; m_SaveState = true;
@ -357,15 +402,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
else else
{ {
m_log.WarnFormat( m_log.WarnFormat(
"[SCRIPT INSTANCE]: Unable to load script state file {0} for script {1} {2} in {3} {4} (assembly {5}). Memory limit exceeded", "[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.",
savedState, ScriptName, ItemID, PrimName, ObjectID, assembly); ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, savedState);
} }
} }
catch (Exception e) catch (Exception e)
{ {
m_log.ErrorFormat( 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}", "[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}",
savedState, ScriptName, ItemID, PrimName, ObjectID, assembly, xml, e.Message, e.StackTrace); ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, savedState, xml, e.Message, e.StackTrace);
} }
} }
// else // else
@ -376,6 +421,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
// presence.ControllingClient.SendAgentAlertMessage("Compile successful", false); // presence.ControllingClient.SendAgentAlertMessage("Compile successful", false);
// } // }
return true;
} }
public void Init() public void Init()
@ -552,6 +599,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
} }
else else
{ {
if (DebugLevel >= 1)
m_log.DebugFormat( m_log.DebugFormat(
"[SCRIPT INSTANCE]: Co-operatively stopping script {0} {1} in {2} {3}", "[SCRIPT INSTANCE]: Co-operatively stopping script {0} {1} in {2} {3}",
ScriptName, ItemID, PrimName, ObjectID); ScriptName, ItemID, PrimName, ObjectID);
@ -563,6 +611,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
// checking is implemented. May want to allow a shorter timeout option later. // checking is implemented. May want to allow a shorter timeout option later.
if (workItem.Wait(TimeSpan.MaxValue)) if (workItem.Wait(TimeSpan.MaxValue))
{ {
if (DebugLevel >= 1)
m_log.DebugFormat( m_log.DebugFormat(
"[SCRIPT INSTANCE]: Co-operatively stopped script {0} {1} in {2} {3}", "[SCRIPT INSTANCE]: Co-operatively stopped script {0} {1} in {2} {3}",
ScriptName, ItemID, PrimName, ObjectID); ScriptName, ItemID, PrimName, ObjectID);
@ -876,6 +925,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
} }
else if ((e is TargetInvocationException) && (e.InnerException is ScriptCoopStopException)) else if ((e is TargetInvocationException) && (e.InnerException is ScriptCoopStopException))
{ {
if (DebugLevel >= 1)
m_log.DebugFormat( m_log.DebugFormat(
"[SCRIPT INSTANCE]: Script {0}.{1} in event {2}, state {3} stopped co-operatively.", "[SCRIPT INSTANCE]: Script {0}.{1} in event {2}, state {3} stopped co-operatively.",
PrimName, ScriptName, data.EventName, State); PrimName, ScriptName, data.EventName, State);

View File

@ -50,14 +50,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
private TestScene m_scene; private TestScene m_scene;
private OpenSim.Region.ScriptEngine.XEngine.XEngine m_xEngine; private OpenSim.Region.ScriptEngine.XEngine.XEngine m_xEngine;
private AutoResetEvent m_chatEvent = new AutoResetEvent(false); private AutoResetEvent m_chatEvent;
private AutoResetEvent m_stoppedEvent = new AutoResetEvent(false); private AutoResetEvent m_stoppedEvent;
private OSChatMessage m_osChatMessageReceived; private OSChatMessage m_osChatMessageReceived;
[TestFixtureSetUp] [SetUp]
public void Init() public void Init()
{ {
m_osChatMessageReceived = null;
m_chatEvent = new AutoResetEvent(false);
m_stoppedEvent = new AutoResetEvent(false);
//AppDomain.CurrentDomain.SetData("APPBASE", Environment.CurrentDirectory + "/bin"); //AppDomain.CurrentDomain.SetData("APPBASE", Environment.CurrentDirectory + "/bin");
// Console.WriteLine(AppDomain.CurrentDomain.BaseDirectory); // Console.WriteLine(AppDomain.CurrentDomain.BaseDirectory);
m_xEngine = new OpenSim.Region.ScriptEngine.XEngine.XEngine(); m_xEngine = new OpenSim.Region.ScriptEngine.XEngine.XEngine();
@ -77,7 +81,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
xEngineConfig.Set("ScriptStopStrategy", "co-op"); xEngineConfig.Set("ScriptStopStrategy", "co-op");
m_scene = new SceneHelpers().SetupScene("My Test", UUID.Random(), 1000, 1000, configSource); // Make sure loops aren't actually being terminated by a script delay wait.
xEngineConfig.Set("ScriptDelayFactor", 0);
// This is really just set for debugging the test.
xEngineConfig.Set("WriteScriptSourceToDebugFile", true);
// Set to false if we need to debug test so the old scripts don't get wiped before each separate test
// xEngineConfig.Set("DeleteScriptsOnStartup", false);
// This is not currently used at all for co-op termination. Bumping up to demonstrate that co-op termination
// has an effect - without it tests will fail due to a 120 second wait for the event to finish.
xEngineConfig.Set("WaitForEventCompletionOnScriptStop", 120000);
m_scene = new SceneHelpers().SetupScene("My Test", TestHelpers.ParseTail(0x9999), 1000, 1000, configSource);
SceneHelpers.SetupSceneModules(m_scene, configSource, m_xEngine); SceneHelpers.SetupSceneModules(m_scene, configSource, m_xEngine);
m_scene.StartScripts(); m_scene.StartScripts();
} }
@ -95,12 +112,218 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
TestHelpers.InMethod(); TestHelpers.InMethod();
// TestHelpers.EnableLogging(); // TestHelpers.EnableLogging();
string script =
@"default
{
state_entry()
{
llSay(0, ""Thin Lizzy"");
llSleep(60);
}
}";
TestStop(script);
}
[Test]
public void TestStopOnLongSingleStatementForLoop()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
string script =
@"default
{
state_entry()
{
integer i = 0;
llSay(0, ""Thin Lizzy"");
for (i = 0; i < 2147483647; i++)
llSay(0, ""Iter "" + (string)i);
}
}";
TestStop(script);
}
[Test]
public void TestStopOnLongCompoundStatementForLoop()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
string script =
@"default
{
state_entry()
{
integer i = 0;
llSay(0, ""Thin Lizzy"");
for (i = 0; i < 2147483647; i++)
{
llSay(0, ""Iter "" + (string)i);
}
}
}";
TestStop(script);
}
[Test]
public void TestStopOnLongSingleStatementWhileLoop()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
string script =
@"default
{
state_entry()
{
integer i = 0;
llSay(0, ""Thin Lizzy"");
while (1 == 1)
llSay(0, ""Iter "" + (string)i++);
}
}";
TestStop(script);
}
[Test]
public void TestStopOnLongCompoundStatementWhileLoop()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
string script =
@"default
{
state_entry()
{
integer i = 0;
llSay(0, ""Thin Lizzy"");
while (1 == 1)
{
llSay(0, ""Iter "" + (string)i++);
}
}
}";
TestStop(script);
}
[Test]
public void TestStopOnLongDoWhileLoop()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
string script =
@"default
{
state_entry()
{
integer i = 0;
llSay(0, ""Thin Lizzy"");
do
{
llSay(0, ""Iter "" + (string)i++);
} while (1 == 1);
}
}";
TestStop(script);
}
[Test]
public void TestStopOnInfiniteJumpLoop()
{
TestHelpers.InMethod();
TestHelpers.EnableLogging();
string script =
@"default
{
state_entry()
{
integer i = 0;
llSay(0, ""Thin Lizzy"");
@p1;
llSay(0, ""Iter "" + (string)i++);
jump p1;
}
}";
TestStop(script);
}
[Test]
public void TestStopOnInfiniteUserFunctionCallLoop()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
string script =
@"
integer i = 0;
ufn1()
{
llSay(0, ""Iter ufn1() "" + (string)i++);
ufn1();
}
default
{
state_entry()
{
integer i = 0;
llSay(0, ""Thin Lizzy"");
ufn1();
}
}";
TestStop(script);
}
[Test]
public void TestStopOnInfiniteManualEventCallLoop()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
string script =
@"default
{
state_entry()
{
integer i = 0;
llSay(0, ""Thin Lizzy"");
llSay(0, ""Iter"" + (string)i++);
default_event_state_entry();
}
}";
TestStop(script);
}
private void TestStop(string script)
{
UUID userId = TestHelpers.ParseTail(0x1); UUID userId = TestHelpers.ParseTail(0x1);
// UUID objectId = TestHelpers.ParseTail(0x100); // UUID objectId = TestHelpers.ParseTail(0x100);
// UUID itemId = TestHelpers.ParseTail(0x3); // UUID itemId = TestHelpers.ParseTail(0x3);
string itemName = "TestStopOnObjectDerezLongSleep() Item"; string itemName = "TestStop() Item";
SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, "TestStopOnObjectDerezLongSleep", 0x100); SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, "TestStop", 0x100);
m_scene.AddNewSceneObject(so, true); m_scene.AddNewSceneObject(so, true);
InventoryItemBase itemTemplate = new InventoryItemBase(); InventoryItemBase itemTemplate = new InventoryItemBase();
@ -111,15 +334,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
m_scene.EventManager.OnChatFromWorld += OnChatFromWorld; m_scene.EventManager.OnChatFromWorld += OnChatFromWorld;
SceneObjectPart partWhereRezzed = m_scene.RezNewScript(userId, itemTemplate, SceneObjectPart partWhereRezzed = m_scene.RezNewScript(userId, itemTemplate, script);
@"default
{
state_entry()
{
llSay(0, ""Thin Lizzy"");
llSleep(60);
}
}");
TaskInventoryItem rezzedItem = partWhereRezzed.Inventory.GetInventoryItem(itemName); TaskInventoryItem rezzedItem = partWhereRezzed.Inventory.GetInventoryItem(itemName);
@ -129,7 +344,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
Console.WriteLine("Script started with message [{0}]", m_osChatMessageReceived.Message); 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 // 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); Thread.Sleep(1000);
// We need a way of carrying on if StopScript() fail, since it won't return if the script isn't actually // We need a way of carrying on if StopScript() fail, since it won't return if the script isn't actually
@ -148,7 +363,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
private void OnChatFromWorld(object sender, OSChatMessage oscm) 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_osChatMessageReceived = oscm;
m_chatEvent.Set(); m_chatEvent.Set();

View File

@ -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
{
/// <summary>
/// Used for script sleeps when we are using co-operative script termination.
/// </summary>
/// <remarks>null if co-operative script termination is not active</remarks>
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();
}
}
}

View File

@ -52,7 +52,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
{ {
myScriptEngine = _ScriptEngine; 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.OnAttach += attach;
myScriptEngine.World.EventManager.OnObjectGrab += touch_start; myScriptEngine.World.EventManager.OnObjectGrab += touch_start;
myScriptEngine.World.EventManager.OnObjectGrabbing += touch; myScriptEngine.World.EventManager.OnObjectGrabbing += touch;

View File

@ -46,13 +46,15 @@ using OpenSim.Framework;
using OpenSim.Framework.Console; using OpenSim.Framework.Console;
using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.ScriptEngine.Interfaces;
using OpenSim.Region.ScriptEngine.Shared; using OpenSim.Region.ScriptEngine.Shared;
using OpenSim.Region.ScriptEngine.Shared.ScriptBase; using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
using OpenSim.Region.ScriptEngine.Shared.CodeTools; using OpenSim.Region.ScriptEngine.Shared.CodeTools;
using OpenSim.Region.ScriptEngine.Shared.Instance; using OpenSim.Region.ScriptEngine.Shared.Instance;
using OpenSim.Region.ScriptEngine.Shared.Api; using OpenSim.Region.ScriptEngine.Shared.Api;
using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
using OpenSim.Region.ScriptEngine.Interfaces; using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
using OpenSim.Region.ScriptEngine.XEngine.ScriptBase;
using Timer = OpenSim.Region.ScriptEngine.Shared.Api.Plugins.Timer; using Timer = OpenSim.Region.ScriptEngine.Shared.Api.Plugins.Timer;
using ScriptCompileQueue = OpenSim.Framework.LocklessQueue<object[]>; using ScriptCompileQueue = OpenSim.Framework.LocklessQueue<object[]>;
@ -176,6 +178,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
get { return "XEngine"; } get { return "XEngine"; }
} }
public string ScriptClassName { get; private set; }
public string ScriptBaseClassName { get; private set; }
public ParameterInfo[] ScriptBaseClassParameters { get; private set; }
public string[] ScriptReferencedAssemblies { get; private set; }
public Scene World public Scene World
{ {
get { return m_Scene; } get { return m_Scene; }
@ -230,21 +240,35 @@ namespace OpenSim.Region.ScriptEngine.XEngine
m_ScriptConfig = configSource.Configs["XEngine"]; m_ScriptConfig = configSource.Configs["XEngine"];
m_ConfigSource = configSource; m_ConfigSource = configSource;
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;
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]);
} }
public void AddRegion(Scene scene) public void AddRegion(Scene scene)
{ {
if (m_ScriptConfig == null) if (m_ScriptConfig == null)
return; return;
m_ScriptFailCount = 0; m_ScriptFailCount = 0;
m_ScriptErrorMessage = String.Empty; 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); m_Enabled = m_ScriptConfig.GetBoolean("Enabled", true);
if (!m_Enabled) if (!m_Enabled)
@ -1109,7 +1133,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
} }
m_log.DebugFormat( 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.Name, item.Name, itemID, part.UUID,
part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
@ -1130,6 +1154,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
lock (m_AddingAssemblies) lock (m_AddingAssemblies)
{ {
m_Compiler.PerformScriptCompile(script, assetID.ToString(), item.OwnerID, out assembly, out linemap); m_Compiler.PerformScriptCompile(script, assetID.ToString(), item.OwnerID, out assembly, out linemap);
if (!m_AddingAssemblies.ContainsKey(assembly)) { if (!m_AddingAssemblies.ContainsKey(assembly)) {
m_AddingAssemblies[assembly] = 1; m_AddingAssemblies[assembly] = 1;
} else { } else {
@ -1179,7 +1204,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
} }
catch (Exception e) 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 // try
// { // {
@ -1288,7 +1315,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
startParam, postOnRez, startParam, postOnRez,
m_MaxScriptQueue); m_MaxScriptQueue);
instance.Load(m_AppDomains[appDomain], assembly, stateSource); if (!instance.Load(m_AppDomains[appDomain], assembly, stateSource))
return false;
// if (DebugLevel >= 1) // if (DebugLevel >= 1)
// m_log.DebugFormat( // m_log.DebugFormat(

View File

@ -749,13 +749,6 @@
;; The trade-off may be increased memory usage by the script engine. ;; The trade-off may be increased memory usage by the script engine.
; ThreadStackSize = 262144 ; 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 ;; Set this to true (the default) to load each script into a separate
;; AppDomain. ;; AppDomain.
;; ;;
@ -768,6 +761,23 @@
;; Some Windows users have also reported script loading problems when AppDomainLoading = false ;; Some Windows users have also reported script loading problems when AppDomainLoading = false
; AppDomainLoading = true ; 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/<region-id>/
;; 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 ;# {DefaultCompileLanguage} {Enabled:true} {Default script language?} {lsl vb cs} lsl
;; Default language for scripts ;; Default language for scripts
; DefaultCompileLanguage = "lsl" ; DefaultCompileLanguage = "lsl"

View File

@ -1315,6 +1315,20 @@
; script assemblies ; script assemblies
AppDomainLoading = true 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/<region-id>/
; 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) ; Rate to poll for asynchronous command replies (ms)
; currently unused ; currently unused
;AsyncLLCommandLoopms = 50 ;AsyncLLCommandLoopms = 50
@ -1416,12 +1430,6 @@
;; Path to script assemblies ;; Path to script assemblies
; ScriptEnginesPath = "ScriptEngines" ; 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] [Concierge]
; Enable concierge module ; Enable concierge module

View File

@ -2391,6 +2391,40 @@
</Files> </Files>
</Project> </Project>
<Project frameworkVersion="v3_5" name="OpenSim.Region.ScriptEngine.XEngine.Api.Runtime" path="OpenSim/Region/ScriptEngine/XEngine/Api/Runtime" type="Library">
<Configuration name="Debug">
<Options>
<OutputPath>../../../../../../bin/</OutputPath>
</Options>
</Configuration>
<Configuration name="Release">
<Options>
<OutputPath>../../../../../../bin/</OutputPath>
</Options>
</Configuration>
<ReferencePath>../../../../../../bin/</ReferencePath>
<Reference name="System"/>
<Reference name="System.Data"/>
<Reference name="System.Web"/>
<Reference name="System.Xml"/>
<Reference name="OpenMetaverseTypes" path="../../../../../../bin/"/>
<Reference name="OpenSim"/>
<Reference name="OpenSim.Framework"/>
<Reference name="OpenSim.Framework.Communications"/>
<Reference name="OpenSim.Region.Framework"/>
<Reference name="OpenSim.Region.CoreModules"/>
<Reference name="OpenSim.Framework.Console"/>
<Reference name="OpenSim.Region.ScriptEngine.Shared"/>
<Reference name="OpenSim.Region.ScriptEngine.Shared.Api.Runtime"/>
<Reference name="Nini" path="../../../../../../bin/"/>
<Reference name="log4net" path="../../../../../../bin/"/>
<Files>
<Match pattern="*.cs" recurse="true"/>
</Files>
</Project>
<Project frameworkVersion="v3_5" name="OpenSim.Region.ScriptEngine.XEngine" path="OpenSim/Region/ScriptEngine/XEngine" type="Library"> <Project frameworkVersion="v3_5" name="OpenSim.Region.ScriptEngine.XEngine" path="OpenSim/Region/ScriptEngine/XEngine" type="Library">
<Configuration name="Debug"> <Configuration name="Debug">
<Options> <Options>
@ -2421,6 +2455,8 @@
<Reference name="OpenSim.Region.ScriptEngine.Shared.CodeTools"/> <Reference name="OpenSim.Region.ScriptEngine.Shared.CodeTools"/>
<Reference name="OpenSim.Region.ScriptEngine.Shared.Instance"/> <Reference name="OpenSim.Region.ScriptEngine.Shared.Instance"/>
<Reference name="OpenSim.Region.ScriptEngine.Shared.Api"/> <Reference name="OpenSim.Region.ScriptEngine.Shared.Api"/>
<Reference name="OpenSim.Region.ScriptEngine.Shared.Api.Runtime"/>
<Reference name="OpenSim.Region.ScriptEngine.XEngine.Api.Runtime"/>
<Reference name="SmartThreadPool"/> <Reference name="SmartThreadPool"/>
<Reference name="Nini" path="../../../../bin/"/> <Reference name="Nini" path="../../../../bin/"/>
<Reference name="log4net" path="../../../../bin/"/> <Reference name="log4net" path="../../../../bin/"/>
@ -2428,6 +2464,7 @@
<Files> <Files>
<Match buildAction="EmbeddedResource" path="Resources" pattern="*.addin.xml" recurse="true"/> <Match buildAction="EmbeddedResource" path="Resources" pattern="*.addin.xml" recurse="true"/>
<Match pattern="*.cs" recurse="true"> <Match pattern="*.cs" recurse="true">
<Exclude name="Api"/>
<Exclude name="Tests" pattern="Tests"/> <Exclude name="Tests" pattern="Tests"/>
</Match> </Match>
</Files> </Files>