aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine')
-rw-r--r--OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs12
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs40
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs88
3 files changed, 116 insertions, 24 deletions
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
index 0cef550..00a99c3 100644
--- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
@@ -59,6 +59,18 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
59 public interface IScriptInstance 59 public interface IScriptInstance
60 { 60 {
61 /// <summary> 61 /// <summary>
62 /// Debug level for this script instance.
63 /// </summary>
64 /// <remarks>
65 /// Level == 0, no extra data is logged.
66 /// Level >= 1, state changes are logged.
67 /// Level >= 2, event firing is logged.
68 /// <value>
69 /// The debug level.
70 /// </value>
71 int DebugLevel { get; set; }
72
73 /// <summary>
62 /// Is the script currently running? 74 /// Is the script currently running?
63 /// </summary> 75 /// </summary>
64 bool Running { get; set; } 76 bool Running { get; set; }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index 538cb8b..68f701c 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -94,6 +94,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
94 private UUID m_CurrentStateHash; 94 private UUID m_CurrentStateHash;
95 private UUID m_RegionID; 95 private UUID m_RegionID;
96 96
97 public int DebugLevel { get; set; }
98
97 public Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> LineMap { get; set; } 99 public Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> LineMap { get; set; }
98 100
99 private Dictionary<string,IScriptApi> m_Apis = new Dictionary<string,IScriptApi>(); 101 private Dictionary<string,IScriptApi> m_Apis = new Dictionary<string,IScriptApi>();
@@ -549,9 +551,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
549 // forcibly abort the work item (this aborts the underlying thread). 551 // forcibly abort the work item (this aborts the underlying thread).
550 if (!m_InSelfDelete) 552 if (!m_InSelfDelete)
551 { 553 {
552// m_log.ErrorFormat( 554 m_log.DebugFormat(
553// "[SCRIPT INSTANCE]: Aborting script {0} {1} in prim {2} {3} {4} {5}", 555 "[SCRIPT INSTANCE]: Aborting unstopped script {0} {1} in prim {2}, localID {3}, timeout was {4} ms",
554// ScriptName, ItemID, PrimName, ObjectID, m_InSelfDelete, DateTime.Now.Ticks); 556 ScriptName, ItemID, PrimName, LocalID, timeout);
555 557
556 workItem.Abort(); 558 workItem.Abort();
557 } 559 }
@@ -707,19 +709,41 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
707 { 709 {
708 710
709// m_log.DebugFormat("[XEngine]: Processing event {0} for {1}", data.EventName, this); 711// m_log.DebugFormat("[XEngine]: Processing event {0} for {1}", data.EventName, this);
712 SceneObjectPart part = Engine.World.GetSceneObjectPart(LocalID);
713
714 if (DebugLevel >= 2)
715 m_log.DebugFormat(
716 "[SCRIPT INSTANCE]: Processing event {0} for {1}/{2}({3})/{4}({5}) @ {6}/{7}",
717 data.EventName,
718 ScriptName,
719 part.Name,
720 part.LocalId,
721 part.ParentGroup.Name,
722 part.ParentGroup.UUID,
723 part.AbsolutePosition,
724 part.ParentGroup.Scene.Name);
710 725
711 m_DetectParams = data.DetectParams; 726 m_DetectParams = data.DetectParams;
712 727
713 if (data.EventName == "state") // Hardcoded state change 728 if (data.EventName == "state") // Hardcoded state change
714 { 729 {
715 // m_log.DebugFormat("[Script] Script {0}.{1} state set to {2}",
716 // PrimName, ScriptName, data.Params[0].ToString());
717 State = data.Params[0].ToString(); 730 State = data.Params[0].ToString();
731
732 if (DebugLevel >= 1)
733 m_log.DebugFormat(
734 "[SCRIPT INSTANCE]: Changing state to {0} for {1}/{2}({3})/{4}({5}) @ {6}/{7}",
735 State,
736 ScriptName,
737 part.Name,
738 part.LocalId,
739 part.ParentGroup.Name,
740 part.ParentGroup.UUID,
741 part.AbsolutePosition,
742 part.ParentGroup.Scene.Name);
743
718 AsyncCommandManager.RemoveScript(Engine, 744 AsyncCommandManager.RemoveScript(Engine,
719 LocalID, ItemID); 745 LocalID, ItemID);
720 746
721 SceneObjectPart part = Engine.World.GetSceneObjectPart(
722 LocalID);
723 if (part != null) 747 if (part != null)
724 { 748 {
725 part.SetScriptEvents(ItemID, 749 part.SetScriptEvents(ItemID,
@@ -731,8 +755,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
731 if (Engine.World.PipeEventsForScript(LocalID) || 755 if (Engine.World.PipeEventsForScript(LocalID) ||
732 data.EventName == "control") // Don't freeze avies! 756 data.EventName == "control") // Don't freeze avies!
733 { 757 {
734 SceneObjectPart part = Engine.World.GetSceneObjectPart(
735 LocalID);
736 // m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}", 758 // m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}",
737 // PrimName, ScriptName, data.EventName, State); 759 // PrimName, ScriptName, data.EventName, State);
738 760
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 05ba890..494e0b6 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -108,6 +108,24 @@ namespace OpenSim.Region.ScriptEngine.XEngine
108 private IXmlRpcRouter m_XmlRpcRouter; 108 private IXmlRpcRouter m_XmlRpcRouter;
109 private int m_EventLimit; 109 private int m_EventLimit;
110 private bool m_KillTimedOutScripts; 110 private bool m_KillTimedOutScripts;
111
112 /// <summary>
113 /// Number of milliseconds we will wait for a script event to complete on script stop before we forcibly abort
114 /// its thread.
115 /// </summary>
116 /// <remarks>
117 /// It appears that if a script thread is aborted whilst it is holding ReaderWriterLockSlim (possibly the write
118 /// lock) then the lock is not properly released. This causes mono 2.6, 2.10 and possibly
119 /// later to crash, sometimes with symptoms such as a leap to 100% script usage and a vm thead dump showing
120 /// all threads waiting on release of ReaderWriterLockSlim write thread which none of the threads listed
121 /// actually hold.
122 ///
123 /// Pausing for event completion reduces the risk of this happening. However, it may be that aborting threads
124 /// is not a mono issue per se but rather a risky activity in itself in an AppDomain that is not immediately
125 /// shutting down.
126 /// </remarks>
127 private int m_WaitForEventCompletionOnScriptStop = 1000;
128
111 private string m_ScriptEnginesPath = null; 129 private string m_ScriptEnginesPath = null;
112 130
113 private ExpiringCache<UUID, bool> m_runFlags = new ExpiringCache<UUID, bool>(); 131 private ExpiringCache<UUID, bool> m_runFlags = new ExpiringCache<UUID, bool>();
@@ -317,6 +335,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
317 m_EventLimit = m_ScriptConfig.GetInt("EventLimit", 30); 335 m_EventLimit = m_ScriptConfig.GetInt("EventLimit", 30);
318 m_KillTimedOutScripts = m_ScriptConfig.GetBoolean("KillTimedOutScripts", false); 336 m_KillTimedOutScripts = m_ScriptConfig.GetBoolean("KillTimedOutScripts", false);
319 m_SaveTime = m_ScriptConfig.GetInt("SaveInterval", 120) * 1000; 337 m_SaveTime = m_ScriptConfig.GetInt("SaveInterval", 120) * 1000;
338 m_WaitForEventCompletionOnScriptStop
339 = m_ScriptConfig.GetInt("WaitForEventCompletionOnScriptStop", m_WaitForEventCompletionOnScriptStop);
340
320 m_ScriptEnginesPath = m_ScriptConfig.GetString("ScriptEnginesPath", "ScriptEngines"); 341 m_ScriptEnginesPath = m_ScriptConfig.GetString("ScriptEnginesPath", "ScriptEngines");
321 342
322 m_Prio = ThreadPriority.BelowNormal; 343 m_Prio = ThreadPriority.BelowNormal;
@@ -372,7 +393,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
372 393
373 MainConsole.Instance.Commands.AddCommand( 394 MainConsole.Instance.Commands.AddCommand(
374 "Scripts", false, "scripts show", "scripts show [<script-item-uuid>]", "Show script information", 395 "Scripts", false, "scripts show", "scripts show [<script-item-uuid>]", "Show script information",
375 "Show information on all scripts known to the script engine." 396 "Show information on all scripts known to the script engine.\n"
376 + "If a <script-item-uuid> is given then only information on that script will be shown.", 397 + "If a <script-item-uuid> is given then only information on that script will be shown.",
377 HandleShowScripts); 398 HandleShowScripts);
378 399
@@ -391,22 +412,30 @@ namespace OpenSim.Region.ScriptEngine.XEngine
391 MainConsole.Instance.Commands.AddCommand( 412 MainConsole.Instance.Commands.AddCommand(
392 "Scripts", false, "scripts resume", "scripts resume [<script-item-uuid>]", "Resumes all suspended scripts", 413 "Scripts", false, "scripts resume", "scripts resume [<script-item-uuid>]", "Resumes all suspended scripts",
393 "Resumes all currently suspended scripts.\n" 414 "Resumes all currently suspended scripts.\n"
394 + "Resumed scripts will process all events accumulated whilst suspended." 415 + "Resumed scripts will process all events accumulated whilst suspended.\n"
395 + "If a <script-item-uuid> is given then only that script will be resumed. Otherwise, all suitable scripts are resumed.", 416 + "If a <script-item-uuid> is given then only that script will be resumed. Otherwise, all suitable scripts are resumed.",
396 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleResumeScript)); 417 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleResumeScript));
397 418
398 MainConsole.Instance.Commands.AddCommand( 419 MainConsole.Instance.Commands.AddCommand(
399 "Scripts", false, "scripts stop", "scripts stop [<script-item-uuid>]", "Stops all running scripts", 420 "Scripts", false, "scripts stop", "scripts stop [<script-item-uuid>]", "Stops all running scripts",
400 "Stops all running scripts." 421 "Stops all running scripts.\n"
401 + "If a <script-item-uuid> is given then only that script will be stopped. Otherwise, all suitable scripts are stopped.", 422 + "If a <script-item-uuid> is given then only that script will be stopped. Otherwise, all suitable scripts are stopped.",
402 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStopScript)); 423 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStopScript));
403 424
404 MainConsole.Instance.Commands.AddCommand( 425 MainConsole.Instance.Commands.AddCommand(
405 "Scripts", false, "scripts start", "scripts start [<script-item-uuid>]", "Starts all stopped scripts", 426 "Scripts", false, "scripts start", "scripts start [<script-item-uuid>]", "Starts all stopped scripts",
406 "Starts all stopped scripts." 427 "Starts all stopped scripts.\n"
407 + "If a <script-item-uuid> is given then only that script will be started. Otherwise, all suitable scripts are started.", 428 + "If a <script-item-uuid> is given then only that script will be started. Otherwise, all suitable scripts are started.",
408 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript)); 429 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript));
409 430
431 MainConsole.Instance.Commands.AddCommand(
432 "Scripts", false, "debug script log", "debug scripts log <item-id> <log-level>", "Extra debug logging for a script",
433 "Activates or deactivates extra debug logging for the given script.\n"
434 + "Level == 0, deactivate extra debug logging.\n"
435 + "Level >= 1, log state changes.\n"
436 + "Level >= 2, log event invocations.\n",
437 HandleDebugScriptLogCommand);
438
410// MainConsole.Instance.Commands.AddCommand( 439// MainConsole.Instance.Commands.AddCommand(
411// "Debug", false, "debug xengine", "debug xengine [<level>]", 440// "Debug", false, "debug xengine", "debug xengine [<level>]",
412// "Turn on detailed xengine debugging.", 441// "Turn on detailed xengine debugging.",
@@ -415,6 +444,41 @@ namespace OpenSim.Region.ScriptEngine.XEngine
415// HandleDebugLevelCommand); 444// HandleDebugLevelCommand);
416 } 445 }
417 446
447 private void HandleDebugScriptLogCommand(string module, string[] args)
448 {
449 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene))
450 return;
451
452 if (args.Length != 5)
453 {
454 MainConsole.Instance.Output("Usage: debug script log <item-id> <log-level>");
455 return;
456 }
457
458 UUID itemId;
459
460 if (!ConsoleUtil.TryParseConsoleUuid(MainConsole.Instance, args[3], out itemId))
461 return;
462
463 int newLevel;
464
465 if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, args[4], out newLevel))
466 return;
467
468 IScriptInstance si;
469
470 lock (m_Scripts)
471 {
472 // XXX: We can't give the user feedback on a bad item id because this may apply to a different script
473 // engine
474 if (!m_Scripts.TryGetValue(itemId, out si))
475 return;
476 }
477
478 si.DebugLevel = newLevel;
479 MainConsole.Instance.OutputFormat("Set debug level of {0} {1} to {2}", si.ScriptName, si.ItemID, newLevel);
480 }
481
418 /// <summary> 482 /// <summary>
419 /// Change debug level 483 /// Change debug level
420 /// </summary> 484 /// </summary>
@@ -486,7 +550,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
486 550
487 if (!UUID.TryParse(rawItemId, out itemId)) 551 if (!UUID.TryParse(rawItemId, out itemId))
488 { 552 {
489 MainConsole.Instance.OutputFormat("Error - {0} is not a valid UUID", rawItemId); 553 MainConsole.Instance.OutputFormat("ERROR: {0} is not a valid UUID", rawItemId);
490 return; 554 return;
491 } 555 }
492 556
@@ -610,6 +674,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
610 sb.AppendFormat("Queued events : {0}\n", instance.EventsQueued); 674 sb.AppendFormat("Queued events : {0}\n", instance.EventsQueued);
611 sb.AppendFormat("Processed events : {0}\n", instance.EventsProcessed); 675 sb.AppendFormat("Processed events : {0}\n", instance.EventsProcessed);
612 sb.AppendFormat("Item UUID : {0}\n", instance.ItemID); 676 sb.AppendFormat("Item UUID : {0}\n", instance.ItemID);
677 sb.AppendFormat("Asset UUID : {0}\n", instance.AssetID);
613 sb.AppendFormat("Containing part name: {0}\n", instance.PrimName); 678 sb.AppendFormat("Containing part name: {0}\n", instance.PrimName);
614 sb.AppendFormat("Containing part UUID: {0}\n", instance.ObjectID); 679 sb.AppendFormat("Containing part UUID: {0}\n", instance.ObjectID);
615 sb.AppendFormat("Position : {0}\n", sop.AbsolutePosition); 680 sb.AppendFormat("Position : {0}\n", sop.AbsolutePosition);
@@ -1375,9 +1440,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1375 lockScriptsForWrite(false); 1440 lockScriptsForWrite(false);
1376 instance.ClearQueue(); 1441 instance.ClearQueue();
1377 1442
1378 // Give the script some time to finish processing its last event. Simply aborting the script thread can 1443 instance.Stop(m_WaitForEventCompletionOnScriptStop);
1379 // cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort.
1380 instance.Stop(1000);
1381 1444
1382// bool objectRemoved = false; 1445// bool objectRemoved = false;
1383 1446
@@ -1735,16 +1798,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1735 public void StopScript(UUID itemID) 1798 public void StopScript(UUID itemID)
1736 { 1799 {
1737 IScriptInstance instance = GetInstance(itemID); 1800 IScriptInstance instance = GetInstance(itemID);
1801
1738 if (instance != null) 1802 if (instance != null)
1739 { 1803 instance.Stop(m_WaitForEventCompletionOnScriptStop);
1740 // Give the script some time to finish processing its last event. Simply aborting the script thread can
1741 // cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort.
1742 instance.Stop(1000);
1743 }
1744 else 1804 else
1745 {
1746 m_runFlags.AddOrUpdate(itemID, false, 240); 1805 m_runFlags.AddOrUpdate(itemID, false, 240);
1747 }
1748 } 1806 }
1749 1807
1750 public DetectParams GetDetectParams(UUID itemID, int idx) 1808 public DetectParams GetDetectParams(UUID itemID, int idx)