Implement co-operative script termination if termination comes during a script wait event (llSleep(), etc.)
This makes use of EventWaitHandles since various web references indicate that Thread.Interrupt() can also cause runtime instability.
If co-op termination is enabled, then termination sets the wait handle instead of waiting for a timeout before possibly aborting the thread.
This allows the script to cleanly terminate if it's in a llSleep/LL function delay or the next time it enters such a wait without any timeout period.
Co-op termination is not yet testable since checking for termination request within loops that never trigger a wait is not yet implemented.
This commit, unlike 1b5c41c
, passes the wait handle as an extra parameter through IScript.Initialize() instead of passing IScriptInstance itself.
user_profiles
parent
b8949024bc
commit
0963ece25b
|
@ -1737,6 +1737,21 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
/// <param name="itemBase"></param>
|
/// <param name="itemBase"></param>
|
||||||
/// <returns>The part where the script was rezzed if successful. False otherwise.</returns>
|
/// <returns>The part where the script was rezzed if successful. False otherwise.</returns>
|
||||||
public SceneObjectPart RezNewScript(UUID agentID, InventoryItemBase itemBase)
|
public SceneObjectPart RezNewScript(UUID agentID, InventoryItemBase itemBase)
|
||||||
|
{
|
||||||
|
return RezNewScript(
|
||||||
|
agentID,
|
||||||
|
itemBase,
|
||||||
|
"default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Rez a new script from nothing with given script text.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="remoteClient"></param>
|
||||||
|
/// <param name="itemBase">Template item.</param>
|
||||||
|
/// <param name="scriptText"></param>
|
||||||
|
/// <returns>The part where the script was rezzed if successful. False otherwise.</returns>
|
||||||
|
public SceneObjectPart RezNewScript(UUID agentID, InventoryItemBase itemBase, string scriptText)
|
||||||
{
|
{
|
||||||
// The part ID is the folder ID!
|
// The part ID is the folder ID!
|
||||||
SceneObjectPart part = GetSceneObjectPart(itemBase.Folder);
|
SceneObjectPart part = GetSceneObjectPart(itemBase.Folder);
|
||||||
|
@ -1757,9 +1772,14 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType,
|
AssetBase asset
|
||||||
Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"),
|
= CreateAsset(
|
||||||
agentID);
|
itemBase.Name,
|
||||||
|
itemBase.Description,
|
||||||
|
(sbyte)itemBase.AssetType,
|
||||||
|
Encoding.ASCII.GetBytes(scriptText),
|
||||||
|
agentID);
|
||||||
|
|
||||||
AssetService.Store(asset);
|
AssetService.Store(asset);
|
||||||
|
|
||||||
TaskInventoryItem taskItem = new TaskInventoryItem();
|
TaskInventoryItem taskItem = new TaskInventoryItem();
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Threading;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
using OpenSim.Region.Framework.Scenes;
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
@ -40,7 +41,11 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// Each API has an identifier, which is used to load the proper runtime assembly at load time.
|
/// Each API has an identifier, which is used to load the proper runtime assembly at load time.
|
||||||
/// <param name='scriptInstance'>/param>
|
/// <param name='scriptEngine'>/param>
|
||||||
void Initialize(IScriptInstance scriptInstance);
|
/// <param name='host'>/param>
|
||||||
|
/// <param name='item'>/param>
|
||||||
|
/// <param name='coopSleepHandle'>/param>
|
||||||
|
void Initialize(
|
||||||
|
IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, EventWaitHandle coopSleepHandle);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -28,6 +28,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using log4net;
|
using log4net;
|
||||||
using OpenSim.Framework;
|
using OpenSim.Framework;
|
||||||
|
|
|
@ -83,9 +83,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi
|
public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi
|
||||||
{
|
{
|
||||||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
protected IScriptEngine m_ScriptEngine;
|
protected IScriptEngine m_ScriptEngine;
|
||||||
protected SceneObjectPart m_host;
|
protected SceneObjectPart m_host;
|
||||||
|
|
||||||
|
/// <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>
|
||||||
|
EventWaitHandle m_coopSleepHandle;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The item that hosts this script
|
/// The item that hosts this script
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -110,13 +117,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp.
|
protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp.
|
||||||
protected ISoundModule m_SoundModule = null;
|
protected ISoundModule m_SoundModule = null;
|
||||||
|
|
||||||
public void Initialize(IScriptInstance scriptInstance)
|
public void Initialize(
|
||||||
|
IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, EventWaitHandle coopSleepHandle)
|
||||||
{
|
{
|
||||||
m_ScriptEngine = scriptInstance.Engine;
|
m_ScriptEngine = scriptEngine;
|
||||||
m_host = scriptInstance.Part;
|
m_host = host;
|
||||||
m_item = scriptInstance.ScriptTask;
|
m_item = item;
|
||||||
|
m_coopSleepHandle = coopSleepHandle;
|
||||||
|
|
||||||
LoadLimits(); // read script limits from config.
|
LoadConfig();
|
||||||
|
|
||||||
m_TransferModule =
|
m_TransferModule =
|
||||||
m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>();
|
m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>();
|
||||||
|
@ -129,7 +138,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Load configuration items that affect script, object and run-time behavior. */
|
/// Load configuration items that affect script, object and run-time behavior. */
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void LoadLimits()
|
private void LoadConfig()
|
||||||
{
|
{
|
||||||
m_ScriptDelayFactor =
|
m_ScriptDelayFactor =
|
||||||
m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f);
|
m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f);
|
||||||
|
@ -175,7 +184,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
delay = (int)((float)delay * m_ScriptDelayFactor);
|
delay = (int)((float)delay * m_ScriptDelayFactor);
|
||||||
if (delay == 0)
|
if (delay == 0)
|
||||||
return;
|
return;
|
||||||
System.Threading.Thread.Sleep(delay);
|
|
||||||
|
Sleep(delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void Sleep(int delay)
|
||||||
|
{
|
||||||
|
if (m_coopSleepHandle == null)
|
||||||
|
System.Threading.Thread.Sleep(delay);
|
||||||
|
else if (m_coopSleepHandle.WaitOne(delay))
|
||||||
|
throw new ScriptCoopStopException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Scene World
|
public Scene World
|
||||||
|
@ -2914,7 +2932,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
{
|
{
|
||||||
// m_log.Info("llSleep snoozing " + sec + "s.");
|
// m_log.Info("llSleep snoozing " + sec + "s.");
|
||||||
m_host.AddScriptLPS(1);
|
m_host.AddScriptLPS(1);
|
||||||
Thread.Sleep((int)(sec * 1000));
|
|
||||||
|
Sleep((int)(sec * 1000));
|
||||||
}
|
}
|
||||||
|
|
||||||
public LSL_Float llGetMass()
|
public LSL_Float llGetMass()
|
||||||
|
|
|
@ -30,6 +30,7 @@ using System.Reflection;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.Remoting.Lifetime;
|
using System.Runtime.Remoting.Lifetime;
|
||||||
|
using System.Threading;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
using OpenSim;
|
using OpenSim;
|
||||||
|
@ -61,10 +62,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
internal bool m_LSFunctionsEnabled = false;
|
internal bool m_LSFunctionsEnabled = false;
|
||||||
internal IScriptModuleComms m_comms = null;
|
internal IScriptModuleComms m_comms = null;
|
||||||
|
|
||||||
public void Initialize(IScriptInstance scriptInstance)
|
public void Initialize(
|
||||||
|
IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, EventWaitHandle coopSleepHandle)
|
||||||
{
|
{
|
||||||
m_ScriptEngine = scriptInstance.Engine;
|
m_ScriptEngine = scriptEngine;
|
||||||
m_host = scriptInstance.Part;
|
m_host = host;
|
||||||
|
|
||||||
if (m_ScriptEngine.Config.GetBoolean("AllowLightShareFunctions", false))
|
if (m_ScriptEngine.Config.GetBoolean("AllowLightShareFunctions", false))
|
||||||
m_LSFunctionsEnabled = true;
|
m_LSFunctionsEnabled = true;
|
||||||
|
|
|
@ -30,6 +30,7 @@ using System.Reflection;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.Remoting.Lifetime;
|
using System.Runtime.Remoting.Lifetime;
|
||||||
|
using System.Threading;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
using OpenSim;
|
using OpenSim;
|
||||||
|
@ -61,11 +62,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
internal bool m_MODFunctionsEnabled = false;
|
internal bool m_MODFunctionsEnabled = false;
|
||||||
internal IScriptModuleComms m_comms = null;
|
internal IScriptModuleComms m_comms = null;
|
||||||
|
|
||||||
public void Initialize(IScriptInstance scriptInstance)
|
public void Initialize(
|
||||||
|
IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, EventWaitHandle coopSleepHandle)
|
||||||
{
|
{
|
||||||
m_ScriptEngine = scriptInstance.Engine;
|
m_ScriptEngine = scriptEngine;
|
||||||
m_host = scriptInstance.Part;
|
m_host = host;
|
||||||
m_item = scriptInstance.ScriptTask;
|
m_item = item;
|
||||||
|
|
||||||
if (m_ScriptEngine.Config.GetBoolean("AllowMODFunctions", false))
|
if (m_ScriptEngine.Config.GetBoolean("AllowMODFunctions", false))
|
||||||
m_MODFunctionsEnabled = true;
|
m_MODFunctionsEnabled = true;
|
||||||
|
|
|
@ -142,11 +142,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
|
|
||||||
protected IUrlModule m_UrlModule = null;
|
protected IUrlModule m_UrlModule = null;
|
||||||
|
|
||||||
public void Initialize(IScriptInstance scriptInstance)
|
public void Initialize(
|
||||||
|
IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, EventWaitHandle coopSleepHandle)
|
||||||
{
|
{
|
||||||
m_ScriptEngine = scriptInstance.Engine;
|
m_ScriptEngine = scriptEngine;
|
||||||
m_host = scriptInstance.Part;
|
m_host = host;
|
||||||
m_item = scriptInstance.ScriptTask;
|
m_item = item;
|
||||||
|
|
||||||
m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
|
m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,24 @@ namespace OpenSim.Region.ScriptEngine.Shared
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used to signal when the script is stopping in co-operation with the script engine
|
||||||
|
/// (instead of through Thread.Abort()).
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public class ScriptCoopStopException : Exception
|
||||||
|
{
|
||||||
|
public ScriptCoopStopException()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ScriptCoopStopException(
|
||||||
|
SerializationInfo info,
|
||||||
|
StreamingContext context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class DetectParams
|
public class DetectParams
|
||||||
{
|
{
|
||||||
public const int AGENT = 1;
|
public const int AGENT = 1;
|
||||||
|
|
|
@ -200,6 +200,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||||
|
|
||||||
public static readonly long MaxMeasurementPeriod = 30 * TimeSpan.TicksPerMinute;
|
public static readonly long MaxMeasurementPeriod = 30 * TimeSpan.TicksPerMinute;
|
||||||
|
|
||||||
|
private bool m_coopTermination;
|
||||||
|
|
||||||
|
private EventWaitHandle m_coopSleepHandle;
|
||||||
|
|
||||||
public void ClearQueue()
|
public void ClearQueue()
|
||||||
{
|
{
|
||||||
m_TimerQueued = false;
|
m_TimerQueued = false;
|
||||||
|
@ -233,6 +237,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||||
m_postOnRez = postOnRez;
|
m_postOnRez = postOnRez;
|
||||||
m_AttachedAvatar = Part.ParentGroup.AttachedAvatar;
|
m_AttachedAvatar = Part.ParentGroup.AttachedAvatar;
|
||||||
m_RegionID = Part.ParentGroup.Scene.RegionInfo.RegionID;
|
m_RegionID = Part.ParentGroup.Scene.RegionInfo.RegionID;
|
||||||
|
|
||||||
|
if (Engine.Config.GetString("ScriptStopStrategy", "abort") == "co-op")
|
||||||
|
{
|
||||||
|
m_coopTermination = true;
|
||||||
|
m_coopSleepHandle = new AutoResetEvent(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -251,7 +261,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||||
foreach (string api in am.GetApis())
|
foreach (string api in am.GetApis())
|
||||||
{
|
{
|
||||||
m_Apis[api] = am.CreateApi(api);
|
m_Apis[api] = am.CreateApi(api);
|
||||||
m_Apis[api].Initialize(this);
|
m_Apis[api].Initialize(Engine, Part, ScriptTask, m_coopSleepHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -532,9 +542,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for the current event to complete.
|
// Wait for the current event to complete.
|
||||||
if (!m_InSelfDelete && workItem.Wait(new TimeSpan((long)timeout * 100000)))
|
if (!m_InSelfDelete)
|
||||||
{
|
{
|
||||||
return true;
|
if (!m_coopTermination)
|
||||||
|
{
|
||||||
|
// If we're not co-operative terminating then try and wait for the event to complete before stopping
|
||||||
|
if (workItem.Wait(new TimeSpan((long)timeout * 100000)))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
|
||||||
|
// For now, we will wait forever since the event should always cleanly terminate once LSL loop
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lock (EventQueue)
|
lock (EventQueue)
|
||||||
|
@ -547,6 +582,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||||
|
|
||||||
// If the event still hasn't stopped and we the stop isn't the result of script or object removal, then
|
// If the event still hasn't stopped and we the stop isn't the result of script or object removal, then
|
||||||
// forcibly abort the work item (this aborts the underlying thread).
|
// forcibly abort the work item (this aborts the underlying thread).
|
||||||
|
// Co-operative termination should never reach this point.
|
||||||
if (!m_InSelfDelete)
|
if (!m_InSelfDelete)
|
||||||
{
|
{
|
||||||
m_log.DebugFormat(
|
m_log.DebugFormat(
|
||||||
|
@ -786,7 +822,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||||
m_InEvent = false;
|
m_InEvent = false;
|
||||||
m_CurrentEvent = String.Empty;
|
m_CurrentEvent = String.Empty;
|
||||||
|
|
||||||
if ((!(e is TargetInvocationException) || (!(e.InnerException is SelfDeleteException) && !(e.InnerException is ScriptDeleteException))) && !(e is ThreadAbortException))
|
if ((!(e is TargetInvocationException)
|
||||||
|
|| (!(e.InnerException is SelfDeleteException)
|
||||||
|
&& !(e.InnerException is ScriptDeleteException)
|
||||||
|
&& !(e.InnerException is ScriptCoopStopException)))
|
||||||
|
&& !(e is ThreadAbortException))
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -834,6 +874,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||||
m_InSelfDelete = true;
|
m_InSelfDelete = true;
|
||||||
Part.Inventory.RemoveInventoryItem(ItemID);
|
Part.Inventory.RemoveInventoryItem(ItemID);
|
||||||
}
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,157 @@
|
||||||
|
/*
|
||||||
|
* 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.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using Nini.Config;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.CoreModules.Scripting.WorldComm;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Region.ScriptEngine.XEngine;
|
||||||
|
using OpenSim.Tests.Common;
|
||||||
|
using OpenSim.Tests.Common.Mock;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Test that co-operative script thread termination is working correctly.
|
||||||
|
/// </summary>
|
||||||
|
[TestFixture]
|
||||||
|
public class CoopTerminationTests : OpenSimTestCase
|
||||||
|
{
|
||||||
|
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 OSChatMessage m_osChatMessageReceived;
|
||||||
|
|
||||||
|
[TestFixtureSetUp]
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
//AppDomain.CurrentDomain.SetData("APPBASE", Environment.CurrentDirectory + "/bin");
|
||||||
|
// Console.WriteLine(AppDomain.CurrentDomain.BaseDirectory);
|
||||||
|
m_xEngine = new OpenSim.Region.ScriptEngine.XEngine.XEngine();
|
||||||
|
|
||||||
|
IniConfigSource configSource = new IniConfigSource();
|
||||||
|
|
||||||
|
IConfig startupConfig = configSource.AddConfig("Startup");
|
||||||
|
startupConfig.Set("DefaultScriptEngine", "XEngine");
|
||||||
|
|
||||||
|
IConfig xEngineConfig = configSource.AddConfig("XEngine");
|
||||||
|
xEngineConfig.Set("Enabled", "true");
|
||||||
|
xEngineConfig.Set("StartDelay", "0");
|
||||||
|
|
||||||
|
// These tests will not run with AppDomainLoading = true, at least on mono. For unknown reasons, the call
|
||||||
|
// to AssemblyResolver.OnAssemblyResolve fails.
|
||||||
|
xEngineConfig.Set("AppDomainLoading", "false");
|
||||||
|
|
||||||
|
xEngineConfig.Set("ScriptStopStrategy", "co-op");
|
||||||
|
|
||||||
|
m_scene = new SceneHelpers().SetupScene("My Test", UUID.Random(), 1000, 1000, configSource);
|
||||||
|
SceneHelpers.SetupSceneModules(m_scene, configSource, m_xEngine);
|
||||||
|
m_scene.StartScripts();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Test co-operative termination on derez of an object containing a script with a long-running event.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// TODO: Actually compiling the script is incidental to this test. Really want a way to compile test scripts
|
||||||
|
/// within the build itself.
|
||||||
|
/// </remarks>
|
||||||
|
[Test]
|
||||||
|
public void TestStopOnLongSleep()
|
||||||
|
{
|
||||||
|
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,
|
||||||
|
@"default
|
||||||
|
{
|
||||||
|
state_entry()
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnChatFromWorld(object sender, OSChatMessage oscm)
|
||||||
|
{
|
||||||
|
// Console.WriteLine("Got chat [{0}]", oscm.Message);
|
||||||
|
|
||||||
|
m_osChatMessageReceived = oscm;
|
||||||
|
m_chatEvent.Set();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -94,7 +94,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
TaskInventoryHelpers.AddSceneObject(m_scene, so1.RootPart, inventoryItemName, itemId, userId);
|
TaskInventoryHelpers.AddSceneObject(m_scene, so1.RootPart, inventoryItemName, itemId, userId);
|
||||||
|
|
||||||
LSL_Api api = new LSL_Api();
|
LSL_Api api = new LSL_Api();
|
||||||
api.Initialize(new ScriptInstance(m_engine, so1.RootPart, null, 0, false, int.MaxValue));
|
api.Initialize(m_engine, so1.RootPart, null, null);
|
||||||
|
|
||||||
// Create a second object
|
// Create a second object
|
||||||
SceneObjectGroup so2 = SceneHelpers.CreateSceneObject(1, userId, "so2", 0x100);
|
SceneObjectGroup so2 = SceneHelpers.CreateSceneObject(1, userId, "so2", 0x100);
|
||||||
|
@ -127,7 +127,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(1, user1Id, "so1", 0x10);
|
SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(1, user1Id, "so1", 0x10);
|
||||||
m_scene.AddSceneObject(so1);
|
m_scene.AddSceneObject(so1);
|
||||||
LSL_Api api = new LSL_Api();
|
LSL_Api api = new LSL_Api();
|
||||||
api.Initialize(new ScriptInstance(m_engine, so1.RootPart, null, 0, false, int.MaxValue));
|
api.Initialize(m_engine, so1.RootPart, null, null);
|
||||||
|
|
||||||
// Create an object embedded inside the first
|
// Create an object embedded inside the first
|
||||||
UUID itemId = TestHelpers.ParseTail(0x20);
|
UUID itemId = TestHelpers.ParseTail(0x20);
|
||||||
|
@ -137,7 +137,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
SceneObjectGroup so2 = SceneHelpers.CreateSceneObject(1, user2Id, "so2", 0x100);
|
SceneObjectGroup so2 = SceneHelpers.CreateSceneObject(1, user2Id, "so2", 0x100);
|
||||||
m_scene.AddSceneObject(so2);
|
m_scene.AddSceneObject(so2);
|
||||||
LSL_Api api2 = new LSL_Api();
|
LSL_Api api2 = new LSL_Api();
|
||||||
api2.Initialize(new ScriptInstance(m_engine, so2.RootPart, null, 0, false, int.MaxValue));
|
api2.Initialize(m_engine, so2.RootPart, null, null);
|
||||||
|
|
||||||
// *** Firstly, we test where llAllowInventoryDrop() has not been called. ***
|
// *** Firstly, we test where llAllowInventoryDrop() has not been called. ***
|
||||||
api.llGiveInventory(so2.UUID.ToString(), inventoryItemName);
|
api.llGiveInventory(so2.UUID.ToString(), inventoryItemName);
|
||||||
|
|
|
@ -105,7 +105,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
m_scene.AddSceneObject(grp2);
|
m_scene.AddSceneObject(grp2);
|
||||||
|
|
||||||
LSL_Api apiGrp1 = new LSL_Api();
|
LSL_Api apiGrp1 = new LSL_Api();
|
||||||
apiGrp1.Initialize(new ScriptInstance(m_engine, grp1.RootPart, grp1Item, 0, false, int.MaxValue));
|
apiGrp1.Initialize(m_engine, grp1.RootPart, grp1Item, null);
|
||||||
|
|
||||||
apiGrp1.llCreateLink(grp2.UUID.ToString(), ScriptBaseClass.TRUE);
|
apiGrp1.llCreateLink(grp2.UUID.ToString(), ScriptBaseClass.TRUE);
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
grp1Item.PermsMask |= ScriptBaseClass.PERMISSION_CHANGE_LINKS;
|
grp1Item.PermsMask |= ScriptBaseClass.PERMISSION_CHANGE_LINKS;
|
||||||
|
|
||||||
LSL_Api apiGrp1 = new LSL_Api();
|
LSL_Api apiGrp1 = new LSL_Api();
|
||||||
apiGrp1.Initialize(new ScriptInstance(m_engine, grp1.RootPart, grp1Item, 0, false, int.MaxValue));
|
apiGrp1.Initialize(m_engine, grp1.RootPart, grp1Item, null);
|
||||||
|
|
||||||
apiGrp1.llBreakLink(2);
|
apiGrp1.llBreakLink(2);
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
engine.AddRegion(scene);
|
engine.AddRegion(scene);
|
||||||
|
|
||||||
m_lslApi = new LSL_Api();
|
m_lslApi = new LSL_Api();
|
||||||
m_lslApi.Initialize(new ScriptInstance(engine, part, null, 0, false, int.MaxValue));
|
m_lslApi.Initialize(engine, part, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
|
|
@ -67,7 +67,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
engine.AddRegion(scene);
|
engine.AddRegion(scene);
|
||||||
|
|
||||||
m_lslApi = new LSL_Api();
|
m_lslApi = new LSL_Api();
|
||||||
m_lslApi.Initialize(new ScriptInstance(engine, part, null, 0, false, int.MaxValue));
|
m_lslApi.Initialize(engine, part, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
|
|
@ -94,7 +94,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
m_scene.AddSceneObject(so);
|
m_scene.AddSceneObject(so);
|
||||||
|
|
||||||
OSSL_Api osslApi = new OSSL_Api();
|
OSSL_Api osslApi = new OSSL_Api();
|
||||||
osslApi.Initialize(new ScriptInstance(m_engine, part, null, 0, false, int.MaxValue));
|
osslApi.Initialize(m_engine, part, null, null);
|
||||||
|
|
||||||
string notecardName = "appearanceNc";
|
string notecardName = "appearanceNc";
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
m_scene.AddSceneObject(so);
|
m_scene.AddSceneObject(so);
|
||||||
|
|
||||||
OSSL_Api osslApi = new OSSL_Api();
|
OSSL_Api osslApi = new OSSL_Api();
|
||||||
osslApi.Initialize(new ScriptInstance(m_engine, part, null, 0, false, int.MaxValue));
|
osslApi.Initialize(m_engine, part, null, null);
|
||||||
|
|
||||||
string notecardName = "appearanceNc";
|
string notecardName = "appearanceNc";
|
||||||
|
|
||||||
|
|
|
@ -99,10 +99,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID);
|
SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID);
|
||||||
TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene, inWorldObj.RootPart);
|
TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene, inWorldObj.RootPart);
|
||||||
|
|
||||||
ScriptInstance si = new ScriptInstance(m_engine, inWorldObj.RootPart, scriptItem, 0, false, int.MaxValue);
|
new LSL_Api().Initialize(m_engine, inWorldObj.RootPart, scriptItem, null);
|
||||||
new LSL_Api().Initialize(si);
|
|
||||||
OSSL_Api osslApi = new OSSL_Api();
|
OSSL_Api osslApi = new OSSL_Api();
|
||||||
osslApi.Initialize(si);
|
osslApi.Initialize(m_engine, inWorldObj.RootPart, scriptItem, null);
|
||||||
|
|
||||||
// SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ua1.PrincipalID);
|
// SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ua1.PrincipalID);
|
||||||
|
|
||||||
|
@ -146,10 +145,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID);
|
SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID);
|
||||||
TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene, inWorldObj.RootPart);
|
TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene, inWorldObj.RootPart);
|
||||||
|
|
||||||
ScriptInstance si = new ScriptInstance(m_engine, inWorldObj.RootPart, scriptItem, 0, false, int.MaxValue);
|
new LSL_Api().Initialize(m_engine, inWorldObj.RootPart, scriptItem, null);
|
||||||
new LSL_Api().Initialize(si);
|
|
||||||
OSSL_Api osslApi = new OSSL_Api();
|
OSSL_Api osslApi = new OSSL_Api();
|
||||||
osslApi.Initialize(si);
|
osslApi.Initialize(m_engine, inWorldObj.RootPart, scriptItem, null);
|
||||||
|
|
||||||
// Create an object embedded inside the first
|
// Create an object embedded inside the first
|
||||||
TaskInventoryHelpers.AddNotecard(
|
TaskInventoryHelpers.AddNotecard(
|
||||||
|
@ -195,10 +193,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID);
|
SceneObjectGroup inWorldObj = SceneHelpers.AddSceneObject(m_scene, "inWorldObj", ua1.PrincipalID);
|
||||||
TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene, inWorldObj.RootPart);
|
TaskInventoryItem scriptItem = TaskInventoryHelpers.AddScript(m_scene, inWorldObj.RootPart);
|
||||||
|
|
||||||
ScriptInstance si = new ScriptInstance(m_engine, inWorldObj.RootPart, scriptItem, 0, false, int.MaxValue);
|
new LSL_Api().Initialize(m_engine, inWorldObj.RootPart, scriptItem, null);
|
||||||
new LSL_Api().Initialize(si);
|
|
||||||
OSSL_Api osslApi = new OSSL_Api();
|
OSSL_Api osslApi = new OSSL_Api();
|
||||||
osslApi.Initialize(si);
|
osslApi.Initialize(m_engine, inWorldObj.RootPart, scriptItem, null);
|
||||||
|
|
||||||
// Create an object embedded inside the first
|
// Create an object embedded inside the first
|
||||||
TaskInventoryHelpers.AddSceneObject(
|
TaskInventoryHelpers.AddSceneObject(
|
||||||
|
|
|
@ -100,7 +100,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
m_scene.AddSceneObject(so);
|
m_scene.AddSceneObject(so);
|
||||||
|
|
||||||
OSSL_Api osslApi = new OSSL_Api();
|
OSSL_Api osslApi = new OSSL_Api();
|
||||||
osslApi.Initialize(new ScriptInstance(m_engine, part, null, 0, false, int.MaxValue));
|
osslApi.Initialize(m_engine, part, null, null);
|
||||||
|
|
||||||
string notecardName = "appearanceNc";
|
string notecardName = "appearanceNc";
|
||||||
osslApi.osOwnerSaveAppearance(notecardName);
|
osslApi.osOwnerSaveAppearance(notecardName);
|
||||||
|
@ -126,7 +126,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
m_scene.AddSceneObject(so);
|
m_scene.AddSceneObject(so);
|
||||||
|
|
||||||
OSSL_Api osslApi = new OSSL_Api();
|
OSSL_Api osslApi = new OSSL_Api();
|
||||||
osslApi.Initialize(new ScriptInstance(m_engine, so.RootPart, null, 0, false, int.MaxValue));
|
osslApi.Initialize(m_engine, so.RootPart, null, null);
|
||||||
|
|
||||||
bool gotExpectedException = false;
|
bool gotExpectedException = false;
|
||||||
try
|
try
|
||||||
|
@ -161,7 +161,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
m_scene.AddSceneObject(so);
|
m_scene.AddSceneObject(so);
|
||||||
|
|
||||||
OSSL_Api osslApi = new OSSL_Api();
|
OSSL_Api osslApi = new OSSL_Api();
|
||||||
osslApi.Initialize(new ScriptInstance(m_engine, part, null, 0, false, int.MaxValue));
|
osslApi.Initialize(m_engine, part, null, null);
|
||||||
|
|
||||||
string notecardName = "appearanceNc";
|
string notecardName = "appearanceNc";
|
||||||
osslApi.osOwnerSaveAppearance(notecardName);
|
osslApi.osOwnerSaveAppearance(notecardName);
|
||||||
|
@ -195,7 +195,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
m_scene.AddSceneObject(so);
|
m_scene.AddSceneObject(so);
|
||||||
|
|
||||||
OSSL_Api osslApi = new OSSL_Api();
|
OSSL_Api osslApi = new OSSL_Api();
|
||||||
osslApi.Initialize(new ScriptInstance(m_engine, part, null, 0, false, int.MaxValue));
|
osslApi.Initialize(m_engine, part, null, null);
|
||||||
|
|
||||||
osslApi.osOwnerSaveAppearance(firstAppearanceNcName);
|
osslApi.osOwnerSaveAppearance(firstAppearanceNcName);
|
||||||
|
|
||||||
|
@ -233,7 +233,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
m_scene.AddSceneObject(so);
|
m_scene.AddSceneObject(so);
|
||||||
|
|
||||||
OSSL_Api osslApi = new OSSL_Api();
|
OSSL_Api osslApi = new OSSL_Api();
|
||||||
osslApi.Initialize(new ScriptInstance(m_engine, part, null, 0, false, int.MaxValue));
|
osslApi.Initialize(m_engine, part, null, null);
|
||||||
|
|
||||||
osslApi.osOwnerSaveAppearance(firstAppearanceNcName);
|
osslApi.osOwnerSaveAppearance(firstAppearanceNcName);
|
||||||
|
|
||||||
|
@ -285,10 +285,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
m_scene.AddSceneObject(otherSo);
|
m_scene.AddSceneObject(otherSo);
|
||||||
|
|
||||||
OSSL_Api osslApi = new OSSL_Api();
|
OSSL_Api osslApi = new OSSL_Api();
|
||||||
osslApi.Initialize(new ScriptInstance(m_engine, part, null, 0, false, int.MaxValue));
|
osslApi.Initialize(m_engine, part, null, null);
|
||||||
|
|
||||||
OSSL_Api otherOsslApi = new OSSL_Api();
|
OSSL_Api otherOsslApi = new OSSL_Api();
|
||||||
otherOsslApi.Initialize(new ScriptInstance(m_engine, otherPart, null, 0, false, int.MaxValue));
|
otherOsslApi.Initialize(m_engine, otherPart, null, null);
|
||||||
|
|
||||||
string notecardName = "appearanceNc";
|
string notecardName = "appearanceNc";
|
||||||
osslApi.osOwnerSaveAppearance(notecardName);
|
osslApi.osOwnerSaveAppearance(notecardName);
|
||||||
|
@ -332,7 +332,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
|
||||||
m_scene.AddSceneObject(so);
|
m_scene.AddSceneObject(so);
|
||||||
|
|
||||||
OSSL_Api osslApi = new OSSL_Api();
|
OSSL_Api osslApi = new OSSL_Api();
|
||||||
osslApi.Initialize(new ScriptInstance(m_engine, part, null, 0, false, int.MaxValue));
|
osslApi.Initialize(m_engine, part, null, null);
|
||||||
|
|
||||||
string notecardName = "appearanceNc";
|
string notecardName = "appearanceNc";
|
||||||
osslApi.osOwnerSaveAppearance(notecardName);
|
osslApi.osOwnerSaveAppearance(notecardName);
|
||||||
|
|
|
@ -1716,9 +1716,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
IScriptInstance instance = GetInstance(itemID);
|
IScriptInstance instance = GetInstance(itemID);
|
||||||
|
|
||||||
if (instance != null)
|
if (instance != null)
|
||||||
|
{
|
||||||
instance.Stop(m_WaitForEventCompletionOnScriptStop);
|
instance.Stop(m_WaitForEventCompletionOnScriptStop);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("[XENGINE]: Could not find script with ID {0} to stop in {1}", itemID, World.Name);
|
||||||
m_runFlags.AddOrUpdate(itemID, false, 240);
|
m_runFlags.AddOrUpdate(itemID, false, 240);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public DetectParams GetDetectParams(UUID itemID, int idx)
|
public DetectParams GetDetectParams(UUID itemID, int idx)
|
||||||
|
|
|
@ -2417,7 +2417,9 @@
|
||||||
<Reference name="log4net" path="../../../../../bin/"/>
|
<Reference name="log4net" path="../../../../../bin/"/>
|
||||||
|
|
||||||
<Files>
|
<Files>
|
||||||
<Match pattern="*.cs" recurse="true"/>
|
<Match pattern="*.cs" recurse="true">
|
||||||
|
<Exclude name="Tests" pattern="Tests"/>
|
||||||
|
</Match>
|
||||||
</Files>
|
</Files>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
||||||
|
@ -3309,6 +3311,7 @@
|
||||||
<!-- SADLY the way this works means you need to keep adding these paths -->
|
<!-- SADLY the way this works means you need to keep adding these paths -->
|
||||||
<Match path="Shared/Tests" pattern="*.cs" recurse="true"/>
|
<Match path="Shared/Tests" pattern="*.cs" recurse="true"/>
|
||||||
<Match path="Shared/CodeTools/Tests" pattern="*.cs" recurse="true"/>
|
<Match path="Shared/CodeTools/Tests" pattern="*.cs" recurse="true"/>
|
||||||
|
<Match path="Shared/Instance/Tests" pattern="*.cs" recurse="true"/>
|
||||||
<Match path="XEngine/Tests" pattern="*.cs" recurse="true"/>
|
<Match path="XEngine/Tests" pattern="*.cs" recurse="true"/>
|
||||||
</Files>
|
</Files>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
Loading…
Reference in New Issue