Merge branch 'master' into careminster

Conflicts:
	OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
This commit is contained in:
Melanie
2013-01-24 00:25:08 +00:00
27 changed files with 758 additions and 260 deletions

View File

@@ -252,7 +252,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
/// <param name='dom'></param>
/// <param name='assembly'></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_stateSource = stateSource;
@@ -267,14 +268,56 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
try
{
if (dom != System.AppDomain.CurrentDomain)
m_Script = (IScript)dom.CreateInstanceAndUnwrap(
Path.GetFileNameWithoutExtension(assembly),
"SecondLife.Script");
object[] constructorParams;
Assembly scriptAssembly = dom.Load(Path.GetFileNameWithoutExtension(assembly));
Type scriptType = scriptAssembly.GetType("SecondLife.XEngineScript");
if (scriptType != null)
{
constructorParams = new object[] { m_coopSleepHandle };
}
else if (!m_coopTermination)
{
scriptType = scriptAssembly.GetType("SecondLife.Script");
constructorParams = null;
}
else
m_Script = (IScript)Assembly.Load(
Path.GetFileNameWithoutExtension(assembly)).CreateInstance(
"SecondLife.Script");
{
m_log.ErrorFormat(
"[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. You must remove all existing {6}* script DLL files before using enabling co-op termination"
+ ", either by setting DeleteScriptsOnStartup = true in [XEngine] for one run"
+ " or by deleting these files manually.",
ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, assembly);
return false;
}
// m_log.DebugFormat(
// "[SCRIPT INSTANCE]: Looking to load {0} from assembly {1} in {2}",
// scriptType.FullName, Path.GetFileNameWithoutExtension(assembly), Engine.World.Name);
if (dom != System.AppDomain.CurrentDomain)
m_Script
= (IScript)dom.CreateInstanceAndUnwrap(
Path.GetFileNameWithoutExtension(assembly),
scriptType.FullName,
false,
BindingFlags.Default,
null,
constructorParams,
null,
null);
else
m_Script
= (IScript)scriptAssembly.CreateInstance(
scriptType.FullName,
false,
BindingFlags.Default,
null,
constructorParams,
null,
null);
//ILease lease = (ILease)RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass);
//RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass);
@@ -283,8 +326,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
catch (Exception e)
{
m_log.ErrorFormat(
"[SCRIPT INSTANCE]: Error loading assembly {0}. Exception {1}{2}",
assembly, e.Message, e.StackTrace);
"[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. Error loading assembly {6}. Exception {7}{8}",
ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, assembly, e.Message, e.StackTrace);
return false;
}
try
@@ -302,10 +347,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
catch (Exception e)
{
m_log.ErrorFormat(
"[SCRIPT INSTANCE]: Error loading script instance from assembly {0}. Exception {1}{2}",
assembly, e.Message, e.StackTrace);
"[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. Error initializing script instance. Exception {6}{7}",
ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, e.Message, e.StackTrace);
return;
return false;
}
m_SaveState = true;
@@ -358,15 +403,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
@@ -377,6 +422,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
// presence.ControllingClient.SendAgentAlertMessage("Compile successful", false);
// }
return true;
}
public void Init()
@@ -560,9 +607,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();
@@ -571,9 +619,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;
}
@@ -894,9 +943,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);
}
}
}

View File

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