aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Shared/Instance
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Shared/Instance')
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs98
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs250
2 files changed, 307 insertions, 41 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index 75aea2b..5bc585e 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -251,7 +251,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
251 /// <param name='dom'></param> 251 /// <param name='dom'></param>
252 /// <param name='assembly'></param> 252 /// <param name='assembly'></param>
253 /// <param name='stateSource'></param> 253 /// <param name='stateSource'></param>
254 public void Load(AppDomain dom, string assembly, StateSource stateSource) 254 /// <returns>false if load failed, true if suceeded</returns>
255 public bool Load(AppDomain dom, string assembly, StateSource stateSource)
255 { 256 {
256 m_Assembly = assembly; 257 m_Assembly = assembly;
257 m_stateSource = stateSource; 258 m_stateSource = stateSource;
@@ -266,14 +267,56 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
266 267
267 try 268 try
268 { 269 {
270 object[] constructorParams;
271
272 Assembly scriptAssembly = dom.Load(Path.GetFileNameWithoutExtension(assembly));
273 Type scriptType = scriptAssembly.GetType("SecondLife.XEngineScript");
274
275 if (scriptType != null)
276 {
277 constructorParams = new object[] { m_coopSleepHandle };
278 }
279 else if (!m_coopTermination)
280 {
281 scriptType = scriptAssembly.GetType("SecondLife.Script");
282 constructorParams = null;
283 }
284 else
285 {
286 m_log.ErrorFormat(
287 "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. You must remove all existing {6}* script DLL files before using enabling co-op termination"
288 + ", either by setting DeleteScriptsOnStartup = true in [XEngine] for one run"
289 + " or by deleting these files manually.",
290 ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, assembly);
291
292 return false;
293 }
294
295// m_log.DebugFormat(
296// "[SCRIPT INSTANCE]: Looking to load {0} from assembly {1} in {2}",
297// scriptType.FullName, Path.GetFileNameWithoutExtension(assembly), Engine.World.Name);
298
269 if (dom != System.AppDomain.CurrentDomain) 299 if (dom != System.AppDomain.CurrentDomain)
270 m_Script = (IScript)dom.CreateInstanceAndUnwrap( 300 m_Script
301 = (IScript)dom.CreateInstanceAndUnwrap(
271 Path.GetFileNameWithoutExtension(assembly), 302 Path.GetFileNameWithoutExtension(assembly),
272 "SecondLife.Script"); 303 scriptType.FullName,
304 false,
305 BindingFlags.Default,
306 null,
307 constructorParams,
308 null,
309 null);
273 else 310 else
274 m_Script = (IScript)Assembly.Load( 311 m_Script
275 Path.GetFileNameWithoutExtension(assembly)).CreateInstance( 312 = (IScript)scriptAssembly.CreateInstance(
276 "SecondLife.Script"); 313 scriptType.FullName,
314 false,
315 BindingFlags.Default,
316 null,
317 constructorParams,
318 null,
319 null);
277 320
278 //ILease lease = (ILease)RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass); 321 //ILease lease = (ILease)RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass);
279 //RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass); 322 //RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass);
@@ -282,8 +325,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
282 catch (Exception e) 325 catch (Exception e)
283 { 326 {
284 m_log.ErrorFormat( 327 m_log.ErrorFormat(
285 "[SCRIPT INSTANCE]: Error loading assembly {0}. Exception {1}{2}", 328 "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. Error loading assembly {6}. Exception {7}{8}",
286 assembly, e.Message, e.StackTrace); 329 ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, assembly, e.Message, e.StackTrace);
330
331 return false;
287 } 332 }
288 333
289 try 334 try
@@ -301,10 +346,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
301 catch (Exception e) 346 catch (Exception e)
302 { 347 {
303 m_log.ErrorFormat( 348 m_log.ErrorFormat(
304 "[SCRIPT INSTANCE]: Error loading script instance from assembly {0}. Exception {1}{2}", 349 "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. Error initializing script instance. Exception {6}{7}",
305 assembly, e.Message, e.StackTrace); 350 ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, e.Message, e.StackTrace);
306 351
307 return; 352 return false;
308 } 353 }
309 354
310 m_SaveState = true; 355 m_SaveState = true;
@@ -357,15 +402,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
357 else 402 else
358 { 403 {
359 m_log.WarnFormat( 404 m_log.WarnFormat(
360 "[SCRIPT INSTANCE]: Unable to load script state file {0} for script {1} {2} in {3} {4} (assembly {5}). Memory limit exceeded", 405 "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. Unable to load script state file {6}. Memory limit exceeded.",
361 savedState, ScriptName, ItemID, PrimName, ObjectID, assembly); 406 ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, savedState);
362 } 407 }
363 } 408 }
364 catch (Exception e) 409 catch (Exception e)
365 { 410 {
366 m_log.ErrorFormat( 411 m_log.ErrorFormat(
367 "[SCRIPT INSTANCE]: Unable to load script state file {0} for script {1} {2} in {3} {4} (assembly {5}). XML is {6}. Exception {7}{8}", 412 "[SCRIPT INSTANCE]: Not starting script {0} (id {1}) in part {2} (id {3}) in object {4} in {5}. Unable to load script state file {6}. XML is {7}. Exception {8}{9}",
368 savedState, ScriptName, ItemID, PrimName, ObjectID, assembly, xml, e.Message, e.StackTrace); 413 ScriptTask.Name, ScriptTask.ItemID, Part.Name, Part.UUID, Part.ParentGroup.Name, Engine.World.Name, savedState, xml, e.Message, e.StackTrace);
369 } 414 }
370 } 415 }
371// else 416// else
@@ -376,6 +421,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
376// presence.ControllingClient.SendAgentAlertMessage("Compile successful", false); 421// presence.ControllingClient.SendAgentAlertMessage("Compile successful", false);
377 422
378// } 423// }
424
425 return true;
379 } 426 }
380 427
381 public void Init() 428 public void Init()
@@ -552,9 +599,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
552 } 599 }
553 else 600 else
554 { 601 {
555 m_log.DebugFormat( 602 if (DebugLevel >= 1)
556 "[SCRIPT INSTANCE]: Co-operatively stopping script {0} {1} in {2} {3}", 603 m_log.DebugFormat(
557 ScriptName, ItemID, PrimName, ObjectID); 604 "[SCRIPT INSTANCE]: Co-operatively stopping script {0} {1} in {2} {3}",
605 ScriptName, ItemID, PrimName, ObjectID);
558 606
559 // This will terminate the event on next handle check by the script. 607 // This will terminate the event on next handle check by the script.
560 m_coopSleepHandle.Set(); 608 m_coopSleepHandle.Set();
@@ -563,9 +611,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
563 // checking is implemented. May want to allow a shorter timeout option later. 611 // checking is implemented. May want to allow a shorter timeout option later.
564 if (workItem.Wait(TimeSpan.MaxValue)) 612 if (workItem.Wait(TimeSpan.MaxValue))
565 { 613 {
566 m_log.DebugFormat( 614 if (DebugLevel >= 1)
567 "[SCRIPT INSTANCE]: Co-operatively stopped script {0} {1} in {2} {3}", 615 m_log.DebugFormat(
568 ScriptName, ItemID, PrimName, ObjectID); 616 "[SCRIPT INSTANCE]: Co-operatively stopped script {0} {1} in {2} {3}",
617 ScriptName, ItemID, PrimName, ObjectID);
569 618
570 return true; 619 return true;
571 } 620 }
@@ -876,9 +925,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
876 } 925 }
877 else if ((e is TargetInvocationException) && (e.InnerException is ScriptCoopStopException)) 926 else if ((e is TargetInvocationException) && (e.InnerException is ScriptCoopStopException))
878 { 927 {
879 m_log.DebugFormat( 928 if (DebugLevel >= 1)
880 "[SCRIPT INSTANCE]: Script {0}.{1} in event {2}, state {3} stopped co-operatively.", 929 m_log.DebugFormat(
881 PrimName, ScriptName, data.EventName, State); 930 "[SCRIPT INSTANCE]: Script {0}.{1} in event {2}, state {3} stopped co-operatively.",
931 PrimName, ScriptName, data.EventName, State);
882 } 932 }
883 } 933 }
884 } 934 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs
index 8c3e9e0..52d75a0 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/Tests/CoopTerminationTests.cs
@@ -50,14 +50,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
50 private TestScene m_scene; 50 private TestScene m_scene;
51 private OpenSim.Region.ScriptEngine.XEngine.XEngine m_xEngine; 51 private OpenSim.Region.ScriptEngine.XEngine.XEngine m_xEngine;
52 52
53 private AutoResetEvent m_chatEvent = new AutoResetEvent(false); 53 private AutoResetEvent m_chatEvent;
54 private AutoResetEvent m_stoppedEvent = new AutoResetEvent(false); 54 private AutoResetEvent m_stoppedEvent;
55 55
56 private OSChatMessage m_osChatMessageReceived; 56 private OSChatMessage m_osChatMessageReceived;
57 57
58 [TestFixtureSetUp] 58 [SetUp]
59 public void Init() 59 public void Init()
60 { 60 {
61 m_osChatMessageReceived = null;
62 m_chatEvent = new AutoResetEvent(false);
63 m_stoppedEvent = new AutoResetEvent(false);
64
61 //AppDomain.CurrentDomain.SetData("APPBASE", Environment.CurrentDirectory + "/bin"); 65 //AppDomain.CurrentDomain.SetData("APPBASE", Environment.CurrentDirectory + "/bin");
62// Console.WriteLine(AppDomain.CurrentDomain.BaseDirectory); 66// Console.WriteLine(AppDomain.CurrentDomain.BaseDirectory);
63 m_xEngine = new OpenSim.Region.ScriptEngine.XEngine.XEngine(); 67 m_xEngine = new OpenSim.Region.ScriptEngine.XEngine.XEngine();
@@ -77,7 +81,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
77 81
78 xEngineConfig.Set("ScriptStopStrategy", "co-op"); 82 xEngineConfig.Set("ScriptStopStrategy", "co-op");
79 83
80 m_scene = new SceneHelpers().SetupScene("My Test", UUID.Random(), 1000, 1000, configSource); 84 // Make sure loops aren't actually being terminated by a script delay wait.
85 xEngineConfig.Set("ScriptDelayFactor", 0);
86
87 // This is really just set for debugging the test.
88 xEngineConfig.Set("WriteScriptSourceToDebugFile", true);
89
90 // Set to false if we need to debug test so the old scripts don't get wiped before each separate test
91// xEngineConfig.Set("DeleteScriptsOnStartup", false);
92
93 // This is not currently used at all for co-op termination. Bumping up to demonstrate that co-op termination
94 // has an effect - without it tests will fail due to a 120 second wait for the event to finish.
95 xEngineConfig.Set("WaitForEventCompletionOnScriptStop", 120000);
96
97 m_scene = new SceneHelpers().SetupScene("My Test", TestHelpers.ParseTail(0x9999), 1000, 1000, configSource);
81 SceneHelpers.SetupSceneModules(m_scene, configSource, m_xEngine); 98 SceneHelpers.SetupSceneModules(m_scene, configSource, m_xEngine);
82 m_scene.StartScripts(); 99 m_scene.StartScripts();
83 } 100 }
@@ -95,12 +112,218 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
95 TestHelpers.InMethod(); 112 TestHelpers.InMethod();
96// TestHelpers.EnableLogging(); 113// TestHelpers.EnableLogging();
97 114
115 string script =
116@"default
117{
118 state_entry()
119 {
120 llSay(0, ""Thin Lizzy"");
121 llSleep(60);
122 }
123}";
124
125 TestStop(script);
126 }
127
128 [Test]
129 public void TestStopOnLongSingleStatementForLoop()
130 {
131 TestHelpers.InMethod();
132// TestHelpers.EnableLogging();
133
134 string script =
135@"default
136{
137 state_entry()
138 {
139 integer i = 0;
140 llSay(0, ""Thin Lizzy"");
141
142 for (i = 0; i < 2147483647; i++)
143 llSay(0, ""Iter "" + (string)i);
144 }
145}";
146
147 TestStop(script);
148 }
149
150 [Test]
151 public void TestStopOnLongCompoundStatementForLoop()
152 {
153 TestHelpers.InMethod();
154// TestHelpers.EnableLogging();
155
156 string script =
157@"default
158{
159 state_entry()
160 {
161 integer i = 0;
162 llSay(0, ""Thin Lizzy"");
163
164 for (i = 0; i < 2147483647; i++)
165 {
166 llSay(0, ""Iter "" + (string)i);
167 }
168 }
169}";
170
171 TestStop(script);
172 }
173
174 [Test]
175 public void TestStopOnLongSingleStatementWhileLoop()
176 {
177 TestHelpers.InMethod();
178// TestHelpers.EnableLogging();
179
180 string script =
181@"default
182{
183 state_entry()
184 {
185 integer i = 0;
186 llSay(0, ""Thin Lizzy"");
187
188 while (1 == 1)
189 llSay(0, ""Iter "" + (string)i++);
190 }
191}";
192
193 TestStop(script);
194 }
195
196 [Test]
197 public void TestStopOnLongCompoundStatementWhileLoop()
198 {
199 TestHelpers.InMethod();
200// TestHelpers.EnableLogging();
201
202 string script =
203@"default
204{
205 state_entry()
206 {
207 integer i = 0;
208 llSay(0, ""Thin Lizzy"");
209
210 while (1 == 1)
211 {
212 llSay(0, ""Iter "" + (string)i++);
213 }
214 }
215}";
216
217 TestStop(script);
218 }
219
220 [Test]
221 public void TestStopOnLongDoWhileLoop()
222 {
223 TestHelpers.InMethod();
224// TestHelpers.EnableLogging();
225
226 string script =
227@"default
228{
229 state_entry()
230 {
231 integer i = 0;
232 llSay(0, ""Thin Lizzy"");
233
234 do
235 {
236 llSay(0, ""Iter "" + (string)i++);
237} while (1 == 1);
238 }
239}";
240
241 TestStop(script);
242 }
243
244 [Test]
245 public void TestStopOnInfiniteJumpLoop()
246 {
247 TestHelpers.InMethod();
248 TestHelpers.EnableLogging();
249
250 string script =
251@"default
252{
253 state_entry()
254 {
255 integer i = 0;
256 llSay(0, ""Thin Lizzy"");
257
258 @p1;
259 llSay(0, ""Iter "" + (string)i++);
260 jump p1;
261 }
262}";
263
264 TestStop(script);
265 }
266
267 [Test]
268 public void TestStopOnInfiniteUserFunctionCallLoop()
269 {
270 TestHelpers.InMethod();
271// TestHelpers.EnableLogging();
272
273 string script =
274@"
275integer i = 0;
276
277ufn1()
278{
279 llSay(0, ""Iter ufn1() "" + (string)i++);
280 ufn1();
281}
282
283default
284{
285 state_entry()
286 {
287 integer i = 0;
288 llSay(0, ""Thin Lizzy"");
289
290 ufn1();
291 }
292}";
293
294 TestStop(script);
295 }
296
297 [Test]
298 public void TestStopOnInfiniteManualEventCallLoop()
299 {
300 TestHelpers.InMethod();
301// TestHelpers.EnableLogging();
302
303 string script =
304@"default
305{
306 state_entry()
307 {
308 integer i = 0;
309 llSay(0, ""Thin Lizzy"");
310
311 llSay(0, ""Iter"" + (string)i++);
312 default_event_state_entry();
313 }
314}";
315
316 TestStop(script);
317 }
318
319 private void TestStop(string script)
320 {
98 UUID userId = TestHelpers.ParseTail(0x1); 321 UUID userId = TestHelpers.ParseTail(0x1);
99// UUID objectId = TestHelpers.ParseTail(0x100); 322// UUID objectId = TestHelpers.ParseTail(0x100);
100// UUID itemId = TestHelpers.ParseTail(0x3); 323// UUID itemId = TestHelpers.ParseTail(0x3);
101 string itemName = "TestStopOnObjectDerezLongSleep() Item"; 324 string itemName = "TestStop() Item";
102 325
103 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, "TestStopOnObjectDerezLongSleep", 0x100); 326 SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, "TestStop", 0x100);
104 m_scene.AddNewSceneObject(so, true); 327 m_scene.AddNewSceneObject(so, true);
105 328
106 InventoryItemBase itemTemplate = new InventoryItemBase(); 329 InventoryItemBase itemTemplate = new InventoryItemBase();
@@ -111,15 +334,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
111 334
112 m_scene.EventManager.OnChatFromWorld += OnChatFromWorld; 335 m_scene.EventManager.OnChatFromWorld += OnChatFromWorld;
113 336
114 SceneObjectPart partWhereRezzed = m_scene.RezNewScript(userId, itemTemplate, 337 SceneObjectPart partWhereRezzed = m_scene.RezNewScript(userId, itemTemplate, script);
115@"default
116{
117 state_entry()
118 {
119 llSay(0, ""Thin Lizzy"");
120 llSleep(60);
121 }
122}");
123 338
124 TaskInventoryItem rezzedItem = partWhereRezzed.Inventory.GetInventoryItem(itemName); 339 TaskInventoryItem rezzedItem = partWhereRezzed.Inventory.GetInventoryItem(itemName);
125 340
@@ -129,7 +344,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
129 Console.WriteLine("Script started with message [{0}]", m_osChatMessageReceived.Message); 344 Console.WriteLine("Script started with message [{0}]", m_osChatMessageReceived.Message);
130 345
131 // FIXME: This is a very poor way of trying to avoid a low-probability race condition where the script 346 // FIXME: This is a very poor way of trying to avoid a low-probability race condition where the script
132 // executes llSay() but has not started the sleep before we try to stop it. 347 // executes llSay() but has not started the next statement before we try to stop it.
133 Thread.Sleep(1000); 348 Thread.Sleep(1000);
134 349
135 // We need a way of carrying on if StopScript() fail, since it won't return if the script isn't actually 350 // We need a way of carrying on if StopScript() fail, since it won't return if the script isn't actually
@@ -148,7 +363,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance.Tests
148 363
149 private void OnChatFromWorld(object sender, OSChatMessage oscm) 364 private void OnChatFromWorld(object sender, OSChatMessage oscm)
150 { 365 {
151// Console.WriteLine("Got chat [{0}]", oscm.Message); 366 m_scene.EventManager.OnChatFromWorld -= OnChatFromWorld;
367 Console.WriteLine("Got chat [{0}]", oscm.Message);
152 368
153 m_osChatMessageReceived = oscm; 369 m_osChatMessageReceived = oscm;
154 m_chatEvent.Set(); 370 m_chatEvent.Set();