aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/XEngine
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine/XEngine')
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Api/Runtime/XEngineScriptBase.cs61
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/EventManager.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/ScriptEngineConsoleCommands.cs126
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs (renamed from OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs)2
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs269
5 files changed, 384 insertions, 78 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Api/Runtime/XEngineScriptBase.cs b/OpenSim/Region/ScriptEngine/XEngine/Api/Runtime/XEngineScriptBase.cs
new file mode 100644
index 0000000..f4211c8
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/Api/Runtime/XEngineScriptBase.cs
@@ -0,0 +1,61 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Runtime.Remoting;
30using System.Runtime.Remoting.Lifetime;
31using System.Security.Permissions;
32using System.Threading;
33using System.Reflection;
34using System.Collections;
35using System.Collections.Generic;
36using OpenSim.Region.ScriptEngine.Interfaces;
37using OpenSim.Region.ScriptEngine.Shared;
38using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
39
40namespace OpenSim.Region.ScriptEngine.XEngine.ScriptBase
41{
42 public class XEngineScriptBase : ScriptBaseClass
43 {
44 /// <summary>
45 /// Used for script sleeps when we are using co-operative script termination.
46 /// </summary>
47 /// <remarks>null if co-operative script termination is not active</remarks>
48 WaitHandle m_coopSleepHandle;
49
50 public XEngineScriptBase(WaitHandle coopSleepHandle) : base()
51 {
52 m_coopSleepHandle = coopSleepHandle;
53 }
54
55 public void opensim_reserved_CheckForCoopTermination()
56 {
57 if (m_coopSleepHandle != null && m_coopSleepHandle.WaitOne(0))
58 throw new ScriptCoopStopException();
59 }
60 }
61} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
index 9405075..afde685 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs
@@ -52,7 +52,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
52 { 52 {
53 myScriptEngine = _ScriptEngine; 53 myScriptEngine = _ScriptEngine;
54 54
55 m_log.Info("[XEngine] Hooking up to server events"); 55// m_log.Info("[XEngine] Hooking up to server events");
56 myScriptEngine.World.EventManager.OnAttach += attach; 56 myScriptEngine.World.EventManager.OnAttach += attach;
57 myScriptEngine.World.EventManager.OnObjectGrab += touch_start; 57 myScriptEngine.World.EventManager.OnObjectGrab += touch_start;
58 myScriptEngine.World.EventManager.OnObjectGrabbing += touch; 58 myScriptEngine.World.EventManager.OnObjectGrabbing += touch;
@@ -69,7 +69,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
69 myScriptEngine.World.EventManager.OnScriptLandColliderStart += land_collision_start; 69 myScriptEngine.World.EventManager.OnScriptLandColliderStart += land_collision_start;
70 myScriptEngine.World.EventManager.OnScriptLandColliding += land_collision; 70 myScriptEngine.World.EventManager.OnScriptLandColliding += land_collision;
71 myScriptEngine.World.EventManager.OnScriptLandColliderEnd += land_collision_end; 71 myScriptEngine.World.EventManager.OnScriptLandColliderEnd += land_collision_end;
72 IMoneyModule money=myScriptEngine.World.RequestModuleInterface<IMoneyModule>(); 72 IMoneyModule money = myScriptEngine.World.RequestModuleInterface<IMoneyModule>();
73 if (money != null) 73 if (money != null)
74 { 74 {
75 money.OnObjectPaid+=HandleObjectPaid; 75 money.OnObjectPaid+=HandleObjectPaid;
diff --git a/OpenSim/Region/ScriptEngine/XEngine/ScriptEngineConsoleCommands.cs b/OpenSim/Region/ScriptEngine/XEngine/ScriptEngineConsoleCommands.cs
new file mode 100644
index 0000000..efb854d
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/XEngine/ScriptEngineConsoleCommands.cs
@@ -0,0 +1,126 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using OpenSim.Framework;
31using OpenSim.Framework.Console;
32using OpenSim.Region.ScriptEngine.Interfaces;
33using OpenSim.Region.ScriptEngine.Shared.Api;
34using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
35
36namespace OpenSim.Region.ScriptEngine.XEngine
37{
38 public class ScriptEngineConsoleCommands
39 {
40 IScriptEngine m_engine;
41
42 public ScriptEngineConsoleCommands(IScriptEngine engine)
43 {
44 m_engine = engine;
45 }
46
47 public void RegisterCommands()
48 {
49 MainConsole.Instance.Commands.AddCommand(
50 "Scripts", false, "show script sensors", "show script sensors", "Show script sensors information",
51 HandleShowSensors);
52
53 MainConsole.Instance.Commands.AddCommand(
54 "Scripts", false, "show script timers", "show script timers", "Show script sensors information",
55 HandleShowTimers);
56 }
57
58 private bool IsSceneSelected()
59 {
60 return MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_engine.World;
61 }
62
63 private void HandleShowSensors(string module, string[] cmdparams)
64 {
65 if (!IsSceneSelected())
66 return;
67
68 SensorRepeat sr = AsyncCommandManager.GetSensorRepeatPlugin(m_engine);
69
70 if (sr == null)
71 {
72 MainConsole.Instance.Output("Plugin not yet initialized");
73 return;
74 }
75
76 List<SensorRepeat.SensorInfo> sensorInfo = sr.GetSensorInfo();
77
78 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
79 cdt.AddColumn("Part name", 40);
80 cdt.AddColumn("Script item ID", 36);
81 cdt.AddColumn("Type", 4);
82 cdt.AddColumn("Interval", 8);
83 cdt.AddColumn("Range", 8);
84 cdt.AddColumn("Arc", 8);
85
86 foreach (SensorRepeat.SensorInfo s in sensorInfo)
87 {
88 cdt.AddRow(s.host.Name, s.itemID, s.type, s.interval, s.range, s.arc);
89 }
90
91 MainConsole.Instance.Output(cdt.ToString());
92 MainConsole.Instance.OutputFormat("Total: {0}", sensorInfo.Count);
93 }
94
95 private void HandleShowTimers(string module, string[] cmdparams)
96 {
97 if (!IsSceneSelected())
98 return;
99
100 Timer timerPlugin = AsyncCommandManager.GetTimerPlugin(m_engine);
101
102 if (timerPlugin == null)
103 {
104 MainConsole.Instance.Output("Plugin not yet initialized");
105 return;
106 }
107
108 List<Timer.TimerInfo> timersInfo = timerPlugin.GetTimersInfo();
109
110 ConsoleDisplayTable cdt = new ConsoleDisplayTable();
111 cdt.AddColumn("Part local ID", 13);
112 cdt.AddColumn("Script item ID", 36);
113 cdt.AddColumn("Interval", 10);
114 cdt.AddColumn("Next", 8);
115
116 foreach (Timer.TimerInfo t in timersInfo)
117 {
118 // Convert from 100 ns ticks back to seconds
119 cdt.AddRow(t.localID, t.itemID, (double)t.interval / 10000000, t.next);
120 }
121
122 MainConsole.Instance.Output(cdt.ToString());
123 MainConsole.Instance.OutputFormat("Total: {0}", timersInfo.Count);
124 }
125 }
126} \ No newline at end of file
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs
index f331658..5abfe9a 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineBasicTests.cs
@@ -44,7 +44,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine.Tests
44 /// XEngine tests. 44 /// XEngine tests.
45 /// </summary> 45 /// </summary>
46 [TestFixture] 46 [TestFixture]
47 public class XEngineTest 47 public class XEngineTest : OpenSimTestCase
48 { 48 {
49 private TestScene m_scene; 49 private TestScene m_scene;
50 private XEngine m_xEngine; 50 private XEngine m_xEngine;
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 9f05666..6e04e79 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -31,6 +31,7 @@ using System.Collections.Generic;
31using System.Diagnostics; //for [DebuggerNonUserCode] 31using System.Diagnostics; //for [DebuggerNonUserCode]
32using System.Globalization; 32using System.Globalization;
33using System.IO; 33using System.IO;
34using System.Linq;
34using System.Reflection; 35using System.Reflection;
35using System.Security; 36using System.Security;
36using System.Security.Policy; 37using System.Security.Policy;
@@ -46,13 +47,15 @@ using OpenSim.Framework;
46using OpenSim.Framework.Console; 47using OpenSim.Framework.Console;
47using OpenSim.Region.Framework.Scenes; 48using OpenSim.Region.Framework.Scenes;
48using OpenSim.Region.Framework.Interfaces; 49using OpenSim.Region.Framework.Interfaces;
50using OpenSim.Region.ScriptEngine.Interfaces;
49using OpenSim.Region.ScriptEngine.Shared; 51using OpenSim.Region.ScriptEngine.Shared;
50using OpenSim.Region.ScriptEngine.Shared.ScriptBase; 52using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
51using OpenSim.Region.ScriptEngine.Shared.CodeTools; 53using OpenSim.Region.ScriptEngine.Shared.CodeTools;
52using OpenSim.Region.ScriptEngine.Shared.Instance; 54using OpenSim.Region.ScriptEngine.Shared.Instance;
53using OpenSim.Region.ScriptEngine.Shared.Api; 55using OpenSim.Region.ScriptEngine.Shared.Api;
54using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; 56using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
55using OpenSim.Region.ScriptEngine.Interfaces; 57using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
58using OpenSim.Region.ScriptEngine.XEngine.ScriptBase;
56using Timer = OpenSim.Region.ScriptEngine.Shared.Api.Plugins.Timer; 59using Timer = OpenSim.Region.ScriptEngine.Shared.Api.Plugins.Timer;
57 60
58using ScriptCompileQueue = OpenSim.Framework.LocklessQueue<object[]>; 61using ScriptCompileQueue = OpenSim.Framework.LocklessQueue<object[]>;
@@ -107,6 +110,24 @@ namespace OpenSim.Region.ScriptEngine.XEngine
107 private IXmlRpcRouter m_XmlRpcRouter; 110 private IXmlRpcRouter m_XmlRpcRouter;
108 private int m_EventLimit; 111 private int m_EventLimit;
109 private bool m_KillTimedOutScripts; 112 private bool m_KillTimedOutScripts;
113
114 /// <summary>
115 /// Number of milliseconds we will wait for a script event to complete on script stop before we forcibly abort
116 /// its thread.
117 /// </summary>
118 /// <remarks>
119 /// It appears that if a script thread is aborted whilst it is holding ReaderWriterLockSlim (possibly the write
120 /// lock) then the lock is not properly released. This causes mono 2.6, 2.10 and possibly
121 /// later to crash, sometimes with symptoms such as a leap to 100% script usage and a vm thead dump showing
122 /// all threads waiting on release of ReaderWriterLockSlim write thread which none of the threads listed
123 /// actually hold.
124 ///
125 /// Pausing for event completion reduces the risk of this happening. However, it may be that aborting threads
126 /// is not a mono issue per se but rather a risky activity in itself in an AppDomain that is not immediately
127 /// shutting down.
128 /// </remarks>
129 private int m_WaitForEventCompletionOnScriptStop = 1000;
130
110 private string m_ScriptEnginesPath = null; 131 private string m_ScriptEnginesPath = null;
111 132
112 private ExpiringCache<UUID, bool> m_runFlags = new ExpiringCache<UUID, bool>(); 133 private ExpiringCache<UUID, bool> m_runFlags = new ExpiringCache<UUID, bool>();
@@ -218,11 +239,21 @@ namespace OpenSim.Region.ScriptEngine.XEngine
218 } 239 }
219 } 240 }
220 241
242 private ScriptEngineConsoleCommands m_consoleCommands;
243
221 public string ScriptEngineName 244 public string ScriptEngineName
222 { 245 {
223 get { return "XEngine"; } 246 get { return "XEngine"; }
224 } 247 }
225 248
249 public string ScriptClassName { get; private set; }
250
251 public string ScriptBaseClassName { get; private set; }
252
253 public ParameterInfo[] ScriptBaseClassParameters { get; private set; }
254
255 public string[] ScriptReferencedAssemblies { get; private set; }
256
226 public Scene World 257 public Scene World
227 { 258 {
228 get { return m_Scene; } 259 get { return m_Scene; }
@@ -277,21 +308,35 @@ namespace OpenSim.Region.ScriptEngine.XEngine
277 308
278 m_ScriptConfig = configSource.Configs["XEngine"]; 309 m_ScriptConfig = configSource.Configs["XEngine"];
279 m_ConfigSource = configSource; 310 m_ConfigSource = configSource;
311
312 string rawScriptStopStrategy = m_ScriptConfig.GetString("ScriptStopStrategy", "abort");
313
314 m_log.InfoFormat("[XEngine]: Script stop strategy is {0}", rawScriptStopStrategy);
315
316 if (rawScriptStopStrategy == "co-op")
317 {
318 ScriptClassName = "XEngineScript";
319 ScriptBaseClassName = typeof(XEngineScriptBase).FullName;
320 ScriptBaseClassParameters = typeof(XEngineScriptBase).GetConstructor(new Type[] { typeof(WaitHandle) }).GetParameters();
321 ScriptReferencedAssemblies = new string[] { Path.GetFileName(typeof(XEngineScriptBase).Assembly.Location) };
322 }
323 else
324 {
325 ScriptClassName = "Script";
326 ScriptBaseClassName = typeof(ScriptBaseClass).FullName;
327 }
328
329// Console.WriteLine("ASSEMBLY NAME: {0}", ScriptReferencedAssemblies[0]);
280 } 330 }
281 331
282 public void AddRegion(Scene scene) 332 public void AddRegion(Scene scene)
283 { 333 {
284 if (m_ScriptConfig == null) 334 if (m_ScriptConfig == null)
285 return; 335 return;
336
286 m_ScriptFailCount = 0; 337 m_ScriptFailCount = 0;
287 m_ScriptErrorMessage = String.Empty; 338 m_ScriptErrorMessage = String.Empty;
288 339
289 if (m_ScriptConfig == null)
290 {
291// m_log.ErrorFormat("[XEngine] No script configuration found. Scripts disabled");
292 return;
293 }
294
295 m_Enabled = m_ScriptConfig.GetBoolean("Enabled", true); 340 m_Enabled = m_ScriptConfig.GetBoolean("Enabled", true);
296 341
297 if (!m_Enabled) 342 if (!m_Enabled)
@@ -316,6 +361,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
316 m_EventLimit = m_ScriptConfig.GetInt("EventLimit", 30); 361 m_EventLimit = m_ScriptConfig.GetInt("EventLimit", 30);
317 m_KillTimedOutScripts = m_ScriptConfig.GetBoolean("KillTimedOutScripts", false); 362 m_KillTimedOutScripts = m_ScriptConfig.GetBoolean("KillTimedOutScripts", false);
318 m_SaveTime = m_ScriptConfig.GetInt("SaveInterval", 120) * 1000; 363 m_SaveTime = m_ScriptConfig.GetInt("SaveInterval", 120) * 1000;
364 m_WaitForEventCompletionOnScriptStop
365 = m_ScriptConfig.GetInt("WaitForEventCompletionOnScriptStop", m_WaitForEventCompletionOnScriptStop);
366
319 m_ScriptEnginesPath = m_ScriptConfig.GetString("ScriptEnginesPath", "ScriptEngines"); 367 m_ScriptEnginesPath = m_ScriptConfig.GetString("ScriptEnginesPath", "ScriptEngines");
320 368
321 m_Prio = ThreadPriority.BelowNormal; 369 m_Prio = ThreadPriority.BelowNormal;
@@ -364,48 +412,59 @@ namespace OpenSim.Region.ScriptEngine.XEngine
364 OnObjectRemoved += m_XmlRpcRouter.ObjectRemoved; 412 OnObjectRemoved += m_XmlRpcRouter.ObjectRemoved;
365 } 413 }
366 414
415 m_consoleCommands = new ScriptEngineConsoleCommands(this);
416 m_consoleCommands.RegisterCommands();
417
367 MainConsole.Instance.Commands.AddCommand( 418 MainConsole.Instance.Commands.AddCommand(
368 "Scripts", false, "xengine status", "xengine status", "Show status information", 419 "Scripts", false, "xengine status", "xengine status", "Show status information",
369 "Show status information on the script engine.", 420 "Show status information on the script engine.",
370 HandleShowStatus); 421 HandleShowStatus);
371 422
372 MainConsole.Instance.Commands.AddCommand( 423 MainConsole.Instance.Commands.AddCommand(
373 "Scripts", false, "scripts show", "scripts show [<script-item-uuid>]", "Show script information", 424 "Scripts", false, "scripts show", "scripts show [<script-item-uuid>+]", "Show script information",
374 "Show information on all scripts known to the script engine." 425 "Show information on all scripts known to the script engine.\n"
375 + "If a <script-item-uuid> is given then only information on that script will be shown.", 426 + "If one or more <script-item-uuid>s are given then only information on that script will be shown.",
376 HandleShowScripts); 427 HandleShowScripts);
377 428
378 MainConsole.Instance.Commands.AddCommand( 429 MainConsole.Instance.Commands.AddCommand(
379 "Scripts", false, "show scripts", "show scripts [<script-item-uuid>]", "Show script information", 430 "Scripts", false, "show scripts", "show scripts [<script-item-uuid>+]", "Show script information",
380 "Synonym for scripts show command", HandleShowScripts); 431 "Synonym for scripts show command", HandleShowScripts);
381 432
382 MainConsole.Instance.Commands.AddCommand( 433 MainConsole.Instance.Commands.AddCommand(
383 "Scripts", false, "scripts suspend", "scripts suspend [<script-item-uuid>]", "Suspends all running scripts", 434 "Scripts", false, "scripts suspend", "scripts suspend [<script-item-uuid>+]", "Suspends all running scripts",
384 "Suspends all currently running scripts. This only suspends event delivery, it will not suspend a" 435 "Suspends all currently running scripts. This only suspends event delivery, it will not suspend a"
385 + " script that is currently processing an event.\n" 436 + " script that is currently processing an event.\n"
386 + "Suspended scripts will continue to accumulate events but won't process them.\n" 437 + "Suspended scripts will continue to accumulate events but won't process them.\n"
387 + "If a <script-item-uuid> is given then only that script will be suspended. Otherwise, all suitable scripts are suspended.", 438 + "If one or more <script-item-uuid>s are given then only that script will be suspended. Otherwise, all suitable scripts are suspended.",
388 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleSuspendScript)); 439 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleSuspendScript));
389 440
390 MainConsole.Instance.Commands.AddCommand( 441 MainConsole.Instance.Commands.AddCommand(
391 "Scripts", false, "scripts resume", "scripts resume [<script-item-uuid>]", "Resumes all suspended scripts", 442 "Scripts", false, "scripts resume", "scripts resume [<script-item-uuid>+]", "Resumes all suspended scripts",
392 "Resumes all currently suspended scripts.\n" 443 "Resumes all currently suspended scripts.\n"
393 + "Resumed scripts will process all events accumulated whilst suspended." 444 + "Resumed scripts will process all events accumulated whilst suspended.\n"
394 + "If a <script-item-uuid> is given then only that script will be resumed. Otherwise, all suitable scripts are resumed.", 445 + "If one or more <script-item-uuid>s are given then only that script will be resumed. Otherwise, all suitable scripts are resumed.",
395 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleResumeScript)); 446 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleResumeScript));
396 447
397 MainConsole.Instance.Commands.AddCommand( 448 MainConsole.Instance.Commands.AddCommand(
398 "Scripts", false, "scripts stop", "scripts stop [<script-item-uuid>]", "Stops all running scripts", 449 "Scripts", false, "scripts stop", "scripts stop [<script-item-uuid>+]", "Stops all running scripts",
399 "Stops all running scripts." 450 "Stops all running scripts.\n"
400 + "If a <script-item-uuid> is given then only that script will be stopped. Otherwise, all suitable scripts are stopped.", 451 + "If one or more <script-item-uuid>s are given then only that script will be stopped. Otherwise, all suitable scripts are stopped.",
401 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStopScript)); 452 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStopScript));
402 453
403 MainConsole.Instance.Commands.AddCommand( 454 MainConsole.Instance.Commands.AddCommand(
404 "Scripts", false, "scripts start", "scripts start [<script-item-uuid>]", "Starts all stopped scripts", 455 "Scripts", false, "scripts start", "scripts start [<script-item-uuid>+]", "Starts all stopped scripts",
405 "Starts all stopped scripts." 456 "Starts all stopped scripts.\n"
406 + "If a <script-item-uuid> is given then only that script will be started. Otherwise, all suitable scripts are started.", 457 + "If one or more <script-item-uuid>s are given then only that script will be started. Otherwise, all suitable scripts are started.",
407 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript)); 458 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript));
408 459
460 MainConsole.Instance.Commands.AddCommand(
461 "Scripts", false, "debug scripts log", "debug scripts log <item-id> <log-level>", "Extra debug logging for a script",
462 "Activates or deactivates extra debug logging for the given script.\n"
463 + "Level == 0, deactivate extra debug logging.\n"
464 + "Level >= 1, log state changes.\n"
465 + "Level >= 2, log event invocations.\n",
466 HandleDebugScriptLogCommand);
467
409// MainConsole.Instance.Commands.AddCommand( 468// MainConsole.Instance.Commands.AddCommand(
410// "Debug", false, "debug xengine", "debug xengine [<level>]", 469// "Debug", false, "debug xengine", "debug xengine [<level>]",
411// "Turn on detailed xengine debugging.", 470// "Turn on detailed xengine debugging.",
@@ -414,6 +473,41 @@ namespace OpenSim.Region.ScriptEngine.XEngine
414// HandleDebugLevelCommand); 473// HandleDebugLevelCommand);
415 } 474 }
416 475
476 private void HandleDebugScriptLogCommand(string module, string[] args)
477 {
478 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene))
479 return;
480
481 if (args.Length != 5)
482 {
483 MainConsole.Instance.Output("Usage: debug script log <item-id> <log-level>");
484 return;
485 }
486
487 UUID itemId;
488
489 if (!ConsoleUtil.TryParseConsoleUuid(MainConsole.Instance, args[3], out itemId))
490 return;
491
492 int newLevel;
493
494 if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, args[4], out newLevel))
495 return;
496
497 IScriptInstance si;
498
499 lock (m_Scripts)
500 {
501 // XXX: We can't give the user feedback on a bad item id because this may apply to a different script
502 // engine
503 if (!m_Scripts.TryGetValue(itemId, out si))
504 return;
505 }
506
507 si.DebugLevel = newLevel;
508 MainConsole.Instance.OutputFormat("Set debug level of {0} {1} to {2}", si.ScriptName, si.ItemID, newLevel);
509 }
510
417 /// <summary> 511 /// <summary>
418 /// Change debug level 512 /// Change debug level
419 /// </summary> 513 /// </summary>
@@ -445,9 +539,21 @@ namespace OpenSim.Region.ScriptEngine.XEngine
445 /// </summary> 539 /// </summary>
446 /// <param name="cmdparams"></param> 540 /// <param name="cmdparams"></param>
447 /// <param name="instance"></param> 541 /// <param name="instance"></param>
448 /// <returns>true if we're okay to proceed, false if not.</returns> 542 /// <param name="comparer">Basis on which to sort output. Can be null if no sort needs to take place</param>
449 private void HandleScriptsAction(string[] cmdparams, Action<IScriptInstance> action) 543 private void HandleScriptsAction(string[] cmdparams, Action<IScriptInstance> action)
450 { 544 {
545 HandleScriptsAction<object>(cmdparams, action, null);
546 }
547
548 /// <summary>
549 /// Parse the raw item id into a script instance from the command params if it's present.
550 /// </summary>
551 /// <param name="cmdparams"></param>
552 /// <param name="instance"></param>
553 /// <param name="keySelector">Basis on which to sort output. Can be null if no sort needs to take place</param>
554 private void HandleScriptsAction<TKey>(
555 string[] cmdparams, Action<IScriptInstance> action, Func<IScriptInstance, TKey> keySelector)
556 {
451 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene)) 557 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene))
452 return; 558 return;
453 559
@@ -458,35 +564,42 @@ namespace OpenSim.Region.ScriptEngine.XEngine
458 564
459 if (cmdparams.Length == 2) 565 if (cmdparams.Length == 2)
460 { 566 {
461 foreach (IScriptInstance instance in m_Scripts.Values) 567 IEnumerable<IScriptInstance> scripts = m_Scripts.Values;
568
569 if (keySelector != null)
570 scripts = scripts.OrderBy<IScriptInstance, TKey>(keySelector);
571
572 foreach (IScriptInstance instance in scripts)
462 action(instance); 573 action(instance);
463 574
464 return; 575 return;
465 } 576 }
466 577
467 rawItemId = cmdparams[2]; 578 for (int i = 2; i < cmdparams.Length; i++)
468
469 if (!UUID.TryParse(rawItemId, out itemId))
470 {
471 MainConsole.Instance.OutputFormat("Error - {0} is not a valid UUID", rawItemId);
472 return;
473 }
474
475 if (itemId != UUID.Zero)
476 { 579 {
477 IScriptInstance instance = GetInstance(itemId); 580 rawItemId = cmdparams[i];
478 if (instance == null) 581
582 if (!UUID.TryParse(rawItemId, out itemId))
479 { 583 {
480 // Commented out for now since this will cause false reports on simulators with more than 584 MainConsole.Instance.OutputFormat("ERROR: {0} is not a valid UUID", rawItemId);
481 // one scene where the current command line set region is 'root' (which causes commands to 585 continue;
482 // go to both regions... (sigh)
483// MainConsole.Instance.OutputFormat("Error - No item found with id {0}", itemId);
484 return;
485 } 586 }
486 else 587
588 if (itemId != UUID.Zero)
487 { 589 {
488 action(instance); 590 IScriptInstance instance = GetInstance(itemId);
489 return; 591 if (instance == null)
592 {
593 // Commented out for now since this will cause false reports on simulators with more than
594 // one scene where the current command line set region is 'root' (which causes commands to
595 // go to both regions... (sigh)
596 // MainConsole.Instance.OutputFormat("Error - No item found with id {0}", itemId);
597 continue;
598 }
599 else
600 {
601 action(instance);
602 }
490 } 603 }
491 } 604 }
492 } 605 }
@@ -505,9 +618,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
505 StringBuilder sb = new StringBuilder(); 618 StringBuilder sb = new StringBuilder();
506 sb.AppendFormat("Status of XEngine instance for {0}\n", m_Scene.RegionInfo.RegionName); 619 sb.AppendFormat("Status of XEngine instance for {0}\n", m_Scene.RegionInfo.RegionName);
507 620
621 long scriptsLoaded, eventsQueued = 0, eventsProcessed = 0;
622
508 lock (m_Scripts) 623 lock (m_Scripts)
509 sb.AppendFormat("Scripts loaded : {0}\n", m_Scripts.Count); 624 {
625 scriptsLoaded = m_Scripts.Count;
510 626
627 foreach (IScriptInstance si in m_Scripts.Values)
628 {
629 eventsQueued += si.EventsQueued;
630 eventsProcessed += si.EventsProcessed;
631 }
632 }
633
634 sb.AppendFormat("Scripts loaded : {0}\n", scriptsLoaded);
511 sb.AppendFormat("Unique scripts : {0}\n", m_uniqueScripts.Count); 635 sb.AppendFormat("Unique scripts : {0}\n", m_uniqueScripts.Count);
512 sb.AppendFormat("Scripts waiting for load : {0}\n", m_CompileQueue.Count); 636 sb.AppendFormat("Scripts waiting for load : {0}\n", m_CompileQueue.Count);
513 sb.AppendFormat("Max threads : {0}\n", m_ThreadPool.MaxThreads); 637 sb.AppendFormat("Max threads : {0}\n", m_ThreadPool.MaxThreads);
@@ -516,6 +640,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
516 sb.AppendFormat("In use threads : {0}\n", m_ThreadPool.InUseThreads); 640 sb.AppendFormat("In use threads : {0}\n", m_ThreadPool.InUseThreads);
517 sb.AppendFormat("Work items waiting : {0}\n", m_ThreadPool.WaitingCallbacks); 641 sb.AppendFormat("Work items waiting : {0}\n", m_ThreadPool.WaitingCallbacks);
518// sb.AppendFormat("Assemblies loaded : {0}\n", m_Assemblies.Count); 642// sb.AppendFormat("Assemblies loaded : {0}\n", m_Assemblies.Count);
643 sb.AppendFormat("Events queued : {0}\n", eventsQueued);
644 sb.AppendFormat("Events processed : {0}\n", eventsProcessed);
519 645
520 SensorRepeat sr = AsyncCommandManager.GetSensorRepeatPlugin(this); 646 SensorRepeat sr = AsyncCommandManager.GetSensorRepeatPlugin(this);
521 sb.AppendFormat("Sensors : {0}\n", sr != null ? sr.SensorsCount : 0); 647 sb.AppendFormat("Sensors : {0}\n", sr != null ? sr.SensorsCount : 0);
@@ -546,7 +672,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
546 } 672 }
547 } 673 }
548 674
549 HandleScriptsAction(cmdparams, HandleShowScript); 675 HandleScriptsAction<long>(cmdparams, HandleShowScript, si => si.EventsProcessed);
550 } 676 }
551 677
552 private void HandleShowScript(IScriptInstance instance) 678 private void HandleShowScript(IScriptInstance instance)
@@ -576,11 +702,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
576 702
577 sb.AppendFormat("Script name : {0}\n", instance.ScriptName); 703 sb.AppendFormat("Script name : {0}\n", instance.ScriptName);
578 sb.AppendFormat("Status : {0}\n", status); 704 sb.AppendFormat("Status : {0}\n", status);
579 705 sb.AppendFormat("Queued events : {0}\n", instance.EventsQueued);
580 lock (eq) 706 sb.AppendFormat("Processed events : {0}\n", instance.EventsProcessed);
581 sb.AppendFormat("Queued events : {0}\n", eq.Count);
582
583 sb.AppendFormat("Item UUID : {0}\n", instance.ItemID); 707 sb.AppendFormat("Item UUID : {0}\n", instance.ItemID);
708 sb.AppendFormat("Asset UUID : {0}\n", instance.AssetID);
584 sb.AppendFormat("Containing part name: {0}\n", instance.PrimName); 709 sb.AppendFormat("Containing part name: {0}\n", instance.PrimName);
585 sb.AppendFormat("Containing part UUID: {0}\n", instance.ObjectID); 710 sb.AppendFormat("Containing part UUID: {0}\n", instance.ObjectID);
586 sb.AppendFormat("Position : {0}\n", sop.AbsolutePosition); 711 sb.AppendFormat("Position : {0}\n", sop.AbsolutePosition);
@@ -1079,7 +1204,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1079 } 1204 }
1080 1205
1081 m_log.DebugFormat( 1206 m_log.DebugFormat(
1082 "[XEngine] Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", 1207 "[XEngine]: Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}",
1083 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, 1208 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
1084 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); 1209 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1085 1210
@@ -1089,8 +1214,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1089 1214
1090 string assembly = ""; 1215 string assembly = "";
1091 1216
1092 CultureInfo USCulture = new CultureInfo("en-US"); 1217 Culture.SetCurrentCulture();
1093 Thread.CurrentThread.CurrentCulture = USCulture;
1094 1218
1095 Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> linemap; 1219 Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> linemap;
1096 1220
@@ -1101,6 +1225,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1101 lock (m_AddingAssemblies) 1225 lock (m_AddingAssemblies)
1102 { 1226 {
1103 m_Compiler.PerformScriptCompile(script, assetID.ToString(), item.OwnerID, out assembly, out linemap); 1227 m_Compiler.PerformScriptCompile(script, assetID.ToString(), item.OwnerID, out assembly, out linemap);
1228
1104 if (!m_AddingAssemblies.ContainsKey(assembly)) { 1229 if (!m_AddingAssemblies.ContainsKey(assembly)) {
1105 m_AddingAssemblies[assembly] = 1; 1230 m_AddingAssemblies[assembly] = 1;
1106 } else { 1231 } else {
@@ -1150,7 +1275,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1150 } 1275 }
1151 catch (Exception e) 1276 catch (Exception e)
1152 { 1277 {
1153// m_log.ErrorFormat("[XEngine]: Exception when rezzing script {0}{1}", e.Message, e.StackTrace); 1278// m_log.ErrorFormat(
1279// "[XEngine]: Exception when rezzing script with item ID {0}, {1}{2}",
1280// itemID, e.Message, e.StackTrace);
1154 1281
1155 // try 1282 // try
1156 // { 1283 // {
@@ -1229,13 +1356,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1229 sandbox = AppDomain.CurrentDomain; 1356 sandbox = AppDomain.CurrentDomain;
1230 } 1357 }
1231 1358
1232 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); 1359 if (!instance.Load(m_AppDomains[appDomain], assembly, stateSource))
1233 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); 1360 return false;
1234 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1235 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1236 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1237 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1238 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1239 1361
1240 m_AppDomains[appDomain] = sandbox; 1362 m_AppDomains[appDomain] = sandbox;
1241 1363
@@ -1256,12 +1378,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1256 m_DomainScripts[appDomain].Add(itemID); 1378 m_DomainScripts[appDomain].Add(itemID);
1257 1379
1258 instance = new ScriptInstance(this, part, 1380 instance = new ScriptInstance(this, part,
1259 itemID, assetID, assembly, 1381 item,
1260 m_AppDomains[appDomain], 1382 startParam, postOnRez,
1261 part.ParentGroup.RootPart.Name, 1383 m_MaxScriptQueue);
1262 item.Name, startParam, postOnRez,
1263 stateSource, m_MaxScriptQueue);
1264 1384
1385 instance.Load(m_AppDomains[appDomain], assembly, stateSource);
1265// m_log.DebugFormat( 1386// m_log.DebugFormat(
1266// "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}", 1387// "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1267// part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, 1388// part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
@@ -1347,9 +1468,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1347 lockScriptsForWrite(false); 1468 lockScriptsForWrite(false);
1348 instance.ClearQueue(); 1469 instance.ClearQueue();
1349 1470
1350 // Give the script some time to finish processing its last event. Simply aborting the script thread can 1471 instance.Stop(m_WaitForEventCompletionOnScriptStop);
1351 // cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort.
1352 instance.Stop(1000);
1353 1472
1354// bool objectRemoved = false; 1473// bool objectRemoved = false;
1355 1474
@@ -1477,7 +1596,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1477 m_MaxScriptQueue = maxScriptQueue; 1596 m_MaxScriptQueue = maxScriptQueue;
1478 1597
1479 STPStartInfo startInfo = new STPStartInfo(); 1598 STPStartInfo startInfo = new STPStartInfo();
1480 startInfo.IdleTimeout = idleTimeout*1000; // convert to seconds as stated in .ini 1599 startInfo.ThreadPoolName = "XEngine";
1600 startInfo.IdleTimeout = idleTimeout * 1000; // convert to seconds as stated in .ini
1481 startInfo.MaxWorkerThreads = maxThreads; 1601 startInfo.MaxWorkerThreads = maxThreads;
1482 startInfo.MinWorkerThreads = minThreads; 1602 startInfo.MinWorkerThreads = minThreads;
1483 startInfo.ThreadPriority = threadPriority;; 1603 startInfo.ThreadPriority = threadPriority;;
@@ -1504,8 +1624,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1504 /// <returns></returns> 1624 /// <returns></returns>
1505 private object ProcessEventHandler(object parms) 1625 private object ProcessEventHandler(object parms)
1506 { 1626 {
1507 CultureInfo USCulture = new CultureInfo("en-US"); 1627 Culture.SetCurrentCulture();
1508 Thread.CurrentThread.CurrentCulture = USCulture;
1509 1628
1510 IScriptInstance instance = (ScriptInstance) parms; 1629 IScriptInstance instance = (ScriptInstance) parms;
1511 1630
@@ -1693,7 +1812,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1693 { 1812 {
1694 IScriptInstance instance = GetInstance(itemID); 1813 IScriptInstance instance = GetInstance(itemID);
1695 if (instance != null) 1814 if (instance != null)
1696 instance.ResetScript(); 1815 instance.ResetScript(m_WaitForEventCompletionOnScriptStop);
1697 } 1816 }
1698 1817
1699 public void StartScript(UUID itemID) 1818 public void StartScript(UUID itemID)
@@ -1708,14 +1827,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1708 public void StopScript(UUID itemID) 1827 public void StopScript(UUID itemID)
1709 { 1828 {
1710 IScriptInstance instance = GetInstance(itemID); 1829 IScriptInstance instance = GetInstance(itemID);
1830
1711 if (instance != null) 1831 if (instance != null)
1712 { 1832 {
1713 // Give the script some time to finish processing its last event. Simply aborting the script thread can 1833 instance.Stop(m_WaitForEventCompletionOnScriptStop);
1714 // cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort.
1715 instance.Stop(1000);
1716 } 1834 }
1717 else 1835 else
1718 { 1836 {
1837// m_log.DebugFormat("[XENGINE]: Could not find script with ID {0} to stop in {1}", itemID, World.Name);
1719 m_runFlags.AddOrUpdate(itemID, false, 240); 1838 m_runFlags.AddOrUpdate(itemID, false, 240);
1720 } 1839 }
1721 } 1840 }