mirror of
https://github.com/opensim/opensim.git
synced 2026-07-15 12:05:49 +08:00
JustinCC's core re-merge
This commit is contained in:
@@ -158,6 +158,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||
|
||||
public UUID AppDomain { get; set; }
|
||||
|
||||
public SceneObjectPart Part { get; private set; }
|
||||
|
||||
public string PrimName { get; private set; }
|
||||
|
||||
public string ScriptName { get; private set; }
|
||||
@@ -199,54 +201,68 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||
|
||||
public static readonly long MaxMeasurementPeriod = 30 * TimeSpan.TicksPerMinute;
|
||||
|
||||
private bool m_coopTermination;
|
||||
|
||||
private EventWaitHandle m_coopSleepHandle;
|
||||
|
||||
public void ClearQueue()
|
||||
{
|
||||
m_TimerQueued = false;
|
||||
EventQueue.Clear();
|
||||
}
|
||||
|
||||
public ScriptInstance(IScriptEngine engine, SceneObjectPart part,
|
||||
UUID itemID, UUID assetID, string assembly,
|
||||
AppDomain dom, string primName, string scriptName,
|
||||
int startParam, bool postOnRez, StateSource stateSource,
|
||||
int maxScriptQueue)
|
||||
public ScriptInstance(
|
||||
IScriptEngine engine, SceneObjectPart part, TaskInventoryItem item,
|
||||
int startParam, bool postOnRez,
|
||||
int maxScriptQueue)
|
||||
{
|
||||
State = "default";
|
||||
EventQueue = new Queue(32);
|
||||
|
||||
Engine = engine;
|
||||
LocalID = part.LocalId;
|
||||
ObjectID = part.UUID;
|
||||
RootLocalID = part.ParentGroup.LocalId;
|
||||
RootObjectID = part.ParentGroup.UUID;
|
||||
ItemID = itemID;
|
||||
AssetID = assetID;
|
||||
PrimName = primName;
|
||||
ScriptName = scriptName;
|
||||
m_Assembly = assembly;
|
||||
Part = part;
|
||||
ScriptTask = item;
|
||||
|
||||
// This is currently only here to allow regression tests to get away without specifying any inventory
|
||||
// item when they are testing script logic that doesn't require an item.
|
||||
if (ScriptTask != null)
|
||||
{
|
||||
ScriptName = ScriptTask.Name;
|
||||
ItemID = ScriptTask.ItemID;
|
||||
AssetID = ScriptTask.AssetID;
|
||||
}
|
||||
|
||||
PrimName = part.ParentGroup.Name;
|
||||
StartParam = startParam;
|
||||
m_MaxScriptQueue = maxScriptQueue;
|
||||
m_stateSource = stateSource;
|
||||
m_postOnRez = postOnRez;
|
||||
m_AttachedAvatar = part.ParentGroup.AttachedAvatar;
|
||||
m_RegionID = part.ParentGroup.Scene.RegionInfo.RegionID;
|
||||
|
||||
if (part != null)
|
||||
if (Engine.Config.GetString("ScriptStopStrategy", "abort") == "co-op")
|
||||
{
|
||||
part.TaskInventory.LockItemsForRead(true);
|
||||
if (part.TaskInventory.ContainsKey(ItemID))
|
||||
{
|
||||
ScriptTask = part.TaskInventory[ItemID];
|
||||
}
|
||||
part.TaskInventory.LockItemsForRead(false);
|
||||
m_coopTermination = true;
|
||||
m_coopSleepHandle = new AutoResetEvent(false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load the script from an assembly into an AppDomain.
|
||||
/// </summary>
|
||||
/// <param name='dom'></param>
|
||||
/// <param name='assembly'></param>
|
||||
/// <param name='stateSource'></param>
|
||||
public void Load(AppDomain dom, string assembly, StateSource stateSource)
|
||||
{
|
||||
m_Assembly = assembly;
|
||||
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_Apis[api].Initialize(Engine, Part, ScriptTask, m_coopSleepHandle);
|
||||
}
|
||||
|
||||
try
|
||||
@@ -280,7 +296,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||
|
||||
// // m_log.Debug("[Script] Script instance created");
|
||||
|
||||
part.SetScriptEvents(ItemID,
|
||||
Part.SetScriptEvents(ItemID,
|
||||
(int)m_Script.GetStateEventFlags(State));
|
||||
}
|
||||
catch (Exception e)
|
||||
@@ -322,7 +338,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||
|
||||
// m_log.DebugFormat("[Script] Successfully retrieved state for script {0}.{1}", PrimName, m_ScriptName);
|
||||
|
||||
part.SetScriptEvents(ItemID,
|
||||
Part.SetScriptEvents(ItemID,
|
||||
(int)m_Script.GetStateEventFlags(State));
|
||||
|
||||
if (!Running)
|
||||
@@ -534,9 +550,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||
}
|
||||
|
||||
// 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)
|
||||
@@ -549,6 +590,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
|
||||
// forcibly abort the work item (this aborts the underlying thread).
|
||||
// Co-operative termination should never reach this point.
|
||||
if (!m_InSelfDelete)
|
||||
{
|
||||
m_log.DebugFormat(
|
||||
@@ -796,7 +838,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||
m_InEvent = false;
|
||||
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
|
||||
{
|
||||
@@ -846,6 +892,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
|
||||
if (part != null)
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user