If [XEngine] ScriptStopStrategy is changed between abort and co-op, for the existing session use the previous strategy for that script rather than not starting the script at all.

We have to do this since we can't unload existing DLLs if they're all in the same AppDomain.
But we can still update the underlying DLL which will be used in the next simulator session.
This commit is contained in:
Justin Clark-Casey (justincc)
2014-07-11 00:03:02 +01:00
parent 6d3b409af2
commit d7b9260496
6 changed files with 112 additions and 68 deletions

View File

@@ -284,12 +284,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
return GetCompilerOutput(assetID.ToString());
}
/// <summary>
/// Converts script from LSL to CS and calls CompileFromCSText
/// </summary>
/// <param name="Script">LSL script</param>
/// <returns>Filename to .dll assembly</returns>
public void PerformScriptCompile(string Script, string asset, UUID ownerUUID,
public void PerformScriptCompile(
string source, string asset, UUID ownerUUID,
out string assembly, out Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> linemap)
{
PerformScriptCompile(source, asset, ownerUUID, false, out assembly, out linemap);
}
public void PerformScriptCompile(
string source, string asset, UUID ownerUUID, bool alwaysRecompile,
out string assembly, out Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> linemap)
{
// m_log.DebugFormat("[Compiler]: Compiling script\n{0}", Script);
@@ -303,9 +306,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
CheckOrCreateScriptsDirectory();
// Don't recompile if we already have it
// Don't recompile if we're not forced to and we already have it
// Performing 3 file exists tests for every script can still be slow
if (File.Exists(assembly) && File.Exists(assembly + ".text") && File.Exists(assembly + ".map"))
if (!alwaysRecompile && File.Exists(assembly) && File.Exists(assembly + ".text") && File.Exists(assembly + ".map"))
{
// If we have already read this linemap file, then it will be in our dictionary.
// Don't build another copy of the dictionary (saves memory) and certainly
@@ -316,29 +319,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
return;
}
if (Script == String.Empty)
{
if (source == String.Empty)
throw new Exception("Cannot find script assembly and no script text present");
}
enumCompileType language = DefaultCompileLanguage;
if (Script.StartsWith("//c#", true, CultureInfo.InvariantCulture))
if (source.StartsWith("//c#", true, CultureInfo.InvariantCulture))
language = enumCompileType.cs;
if (Script.StartsWith("//vb", true, CultureInfo.InvariantCulture))
if (source.StartsWith("//vb", true, CultureInfo.InvariantCulture))
{
language = enumCompileType.vb;
// We need to remove //vb, it won't compile with that
Script = Script.Substring(4, Script.Length - 4);
source = source.Substring(4, source.Length - 4);
}
if (Script.StartsWith("//lsl", true, CultureInfo.InvariantCulture))
if (source.StartsWith("//lsl", true, CultureInfo.InvariantCulture))
language = enumCompileType.lsl;
if (Script.StartsWith("//js", true, CultureInfo.InvariantCulture))
if (source.StartsWith("//js", true, CultureInfo.InvariantCulture))
language = enumCompileType.js;
if (Script.StartsWith("//yp", true, CultureInfo.InvariantCulture))
if (source.StartsWith("//yp", true, CultureInfo.InvariantCulture))
language = enumCompileType.yp;
// m_log.DebugFormat("[Compiler]: Compile language is {0}", language);
@@ -359,13 +360,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools
throw new Exception(errtext);
}
string compileScript = Script;
string compileScript = source;
if (language == enumCompileType.lsl)
{
// Its LSL, convert it to C#
LSL_Converter = (ICodeConverter)new CSCodeGenerator(comms, m_insertCoopTerminationCalls);
compileScript = LSL_Converter.Convert(Script);
compileScript = LSL_Converter.Convert(source);
// copy converter warnings into our warnings.
foreach (string warning in LSL_Converter.GetWarnings())

View File

@@ -67,8 +67,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools.Tests
}
[SetUp]
public void SetUp()
public override void SetUp()
{
base.SetUp();
// Create a CSCodeProvider and CompilerParameters.
m_CSCodeProvider = new CSharpCodeProvider();
m_compilerParameters = new CompilerParameters();

View File

@@ -237,12 +237,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
m_postOnRez = postOnRez;
m_AttachedAvatar = Part.ParentGroup.AttachedAvatar;
m_RegionID = Part.ParentGroup.Scene.RegionInfo.RegionID;
if (Engine.Config.GetString("ScriptStopStrategy", "abort") == "co-op")
{
m_coopTermination = true;
m_coopSleepHandle = new XEngineEventWaitHandle(false, EventResetMode.AutoReset);
}
}
/// <summary>
@@ -252,54 +246,38 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
/// <param name='assembly'></param>
/// <param name='stateSource'></param>
/// <returns>false if load failed, true if suceeded</returns>
public bool Load(AppDomain dom, string assembly, StateSource stateSource)
public bool Load(AppDomain dom, Assembly scriptAssembly, StateSource stateSource)
{
m_Assembly = assembly;
//m_Assembly = scriptAssembly.CodeBase;
m_Assembly = scriptAssembly.Location;
m_stateSource = stateSource;
ApiManager am = new ApiManager();
foreach (string api in am.GetApis())
{
m_Apis[api] = am.CreateApi(api);
m_Apis[api].Initialize(Engine, Part, ScriptTask, m_coopSleepHandle);
}
try
{
object[] constructorParams;
Assembly scriptAssembly = dom.Load(Path.GetFileNameWithoutExtension(assembly));
Type scriptType = scriptAssembly.GetType("SecondLife.XEngineScript");
if (scriptType != null)
{
m_coopTermination = true;
m_coopSleepHandle = new XEngineEventWaitHandle(false, EventResetMode.AutoReset);
constructorParams = new object[] { m_coopSleepHandle };
}
else if (!m_coopTermination)
{
scriptType = scriptAssembly.GetType("SecondLife.Script");
constructorParams = null;
}
else
{
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_coopTermination = false;
scriptType = scriptAssembly.GetType("SecondLife.Script");
constructorParams = null;
}
// m_log.DebugFormat(
// "[SCRIPT INSTANCE]: Looking to load {0} from assembly {1} in {2}",
// scriptType.FullName, Path.GetFileNameWithoutExtension(assembly), Engine.World.Name);
// scriptType.FullName, m_Assembly, Engine.World.Name);
if (dom != System.AppDomain.CurrentDomain)
m_Script
= (IScript)dom.CreateInstanceAndUnwrap(
Path.GetFileNameWithoutExtension(assembly),
Path.GetFileNameWithoutExtension(m_Assembly),
scriptType.FullName,
false,
BindingFlags.Default,
@@ -327,11 +305,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
{
m_log.ErrorFormat(
"[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);
ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, m_Assembly, e.Message, e.StackTrace);
return false;
}
ApiManager am = new ApiManager();
foreach (string api in am.GetApis())
{
m_Apis[api] = am.CreateApi(api);
m_Apis[api].Initialize(Engine, Part, ScriptTask, m_coopSleepHandle);
}
try
{
foreach (KeyValuePair<string,IScriptApi> kv in m_Apis)
@@ -341,8 +327,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
// // m_log.Debug("[Script] Script instance created");
Part.SetScriptEvents(ItemID,
(int)m_Script.GetStateEventFlags(State));
Part.SetScriptEvents(ItemID, (int)m_Script.GetStateEventFlags(State));
}
catch (Exception e)
{
@@ -355,8 +340,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
m_SaveState = true;
string savedState = Path.Combine(Path.GetDirectoryName(assembly),
ItemID.ToString() + ".state");
string savedState = Path.Combine(Path.GetDirectoryName(m_Assembly), ItemID.ToString() + ".state");
if (File.Exists(savedState))
{
string xml = String.Empty;