aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine/XEngine/XEngine.cs')
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs385
1 files changed, 252 insertions, 133 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 5804aa8..27d7674 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Diagnostics; //for [DebuggerNonUserCode]
31using System.Globalization; 32using System.Globalization;
32using System.IO; 33using System.IO;
33using System.Linq; 34using System.Linq;
@@ -148,6 +149,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
148 private Dictionary<UUID, IScriptInstance> m_Scripts = 149 private Dictionary<UUID, IScriptInstance> m_Scripts =
149 new Dictionary<UUID, IScriptInstance>(); 150 new Dictionary<UUID, IScriptInstance>();
150 151
152 private OpenMetaverse.ReaderWriterLockSlim m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
153
151 // Maps the asset ID to the assembly 154 // Maps the asset ID to the assembly
152 155
153 private Dictionary<UUID, string> m_Assemblies = 156 private Dictionary<UUID, string> m_Assemblies =
@@ -170,6 +173,71 @@ namespace OpenSim.Region.ScriptEngine.XEngine
170 IWorkItemResult m_CurrentCompile = null; 173 IWorkItemResult m_CurrentCompile = null;
171 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>(); 174 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>();
172 175
176 private void lockScriptsForRead(bool locked)
177 {
178 if (locked)
179 {
180 if (m_scriptsLock.RecursiveReadCount > 0)
181 {
182 m_log.Error("[XEngine.m_Scripts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
183 m_scriptsLock.ExitReadLock();
184 }
185 if (m_scriptsLock.RecursiveWriteCount > 0)
186 {
187 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
188 m_scriptsLock.ExitWriteLock();
189 }
190
191 while (!m_scriptsLock.TryEnterReadLock(60000))
192 {
193 m_log.Error("[XEngine.m_Scripts] Thread lock detected while trying to aquire READ lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
194 if (m_scriptsLock.IsWriteLockHeld)
195 {
196 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
197 }
198 }
199 }
200 else
201 {
202 if (m_scriptsLock.RecursiveReadCount > 0)
203 {
204 m_scriptsLock.ExitReadLock();
205 }
206 }
207 }
208 private void lockScriptsForWrite(bool locked)
209 {
210 if (locked)
211 {
212 if (m_scriptsLock.RecursiveReadCount > 0)
213 {
214 m_log.Error("[XEngine.m_Scripts] Recursive read lock requested. This should not happen and means something needs to be fixed. For now though, it's safe to continue.");
215 m_scriptsLock.ExitReadLock();
216 }
217 if (m_scriptsLock.RecursiveWriteCount > 0)
218 {
219 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
220 m_scriptsLock.ExitWriteLock();
221 }
222
223 while (!m_scriptsLock.TryEnterWriteLock(60000))
224 {
225 m_log.Error("[XEngine.m_Scripts] Thread lock detected while trying to aquire WRITE lock of m_scripts in XEngine. I'm going to try to solve the thread lock automatically to preserve region stability, but this needs to be fixed.");
226 if (m_scriptsLock.IsWriteLockHeld)
227 {
228 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
229 }
230 }
231 }
232 else
233 {
234 if (m_scriptsLock.RecursiveWriteCount > 0)
235 {
236 m_scriptsLock.ExitWriteLock();
237 }
238 }
239 }
240
173 private ScriptEngineConsoleCommands m_consoleCommands; 241 private ScriptEngineConsoleCommands m_consoleCommands;
174 242
175 public string ScriptEngineName 243 public string ScriptEngineName
@@ -699,64 +767,69 @@ namespace OpenSim.Region.ScriptEngine.XEngine
699 { 767 {
700 if (!m_Enabled) 768 if (!m_Enabled)
701 return; 769 return;
770 lockScriptsForRead(true);
702 771
703 lock (m_Scripts) 772 List<IScriptInstance> instancesToDel = new List<IScriptInstance>(m_Scripts.Values);
704 {
705 m_log.InfoFormat(
706 "[XEngine]: Shutting down {0} scripts in {1}", m_Scripts.Count, m_Scene.RegionInfo.RegionName);
707 773
708 foreach (IScriptInstance instance in m_Scripts.Values) 774// foreach (IScriptInstance instance in m_Scripts.Values)
775 foreach (IScriptInstance instance in instancesToDel)
776 {
777 // Force a final state save
778 //
779 if (m_Assemblies.ContainsKey(instance.AssetID))
709 { 780 {
710 // Force a final state save 781 string assembly = m_Assemblies[instance.AssetID];
711 //
712 if (m_Assemblies.ContainsKey(instance.AssetID))
713 {
714 string assembly = m_Assemblies[instance.AssetID];
715 782
716 try 783 try
717 { 784 {
718 instance.SaveState(assembly); 785 instance.SaveState(assembly);
719 }
720 catch (Exception e)
721 {
722 m_log.Error(
723 string.Format(
724 "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ",
725 instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name)
726 , e);
727 }
728 } 786 }
787 catch (Exception e)
788 {
789 m_log.Error(
790 string.Format(
791 "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ",
792 instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name)
793 , e);
794 }
795 }
729 796
730 // Clear the event queue and abort the instance thread 797 // Clear the event queue and abort the instance thread
731 // 798 //
732 instance.ClearQueue(); 799 instance.ClearQueue();
733 instance.Stop(0); 800 instance.Stop(0);
734 801
735 // Release events, timer, etc 802 // Release events, timer, etc
736 // 803 //
737 instance.DestroyScriptInstance(); 804 instance.DestroyScriptInstance();
738 805
739 // Unload scripts and app domains. 806 // Unload scripts and app domains
740 // Must be done explicitly because they have infinite 807 // Must be done explicitly because they have infinite
741 // lifetime. 808 // lifetime
742 // However, don't bother to do this if the simulator is shutting 809 //
743 // down since it takes a long time with many scripts. 810// if (!m_SimulatorShuttingDown)
744 if (!m_SimulatorShuttingDown) 811 {
812 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
813 if (m_DomainScripts[instance.AppDomain].Count == 0)
745 { 814 {
746 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 815 m_DomainScripts.Remove(instance.AppDomain);
747 if (m_DomainScripts[instance.AppDomain].Count == 0) 816 UnloadAppDomain(instance.AppDomain);
748 {
749 m_DomainScripts.Remove(instance.AppDomain);
750 UnloadAppDomain(instance.AppDomain);
751 }
752 } 817 }
753 } 818 }
754 819
755 m_Scripts.Clear(); 820// m_Scripts.Clear();
756 m_PrimObjects.Clear(); 821// m_PrimObjects.Clear();
757 m_Assemblies.Clear(); 822// m_Assemblies.Clear();
758 m_DomainScripts.Clear(); 823// m_DomainScripts.Clear();
759 } 824 }
825 lockScriptsForRead(false);
826 lockScriptsForWrite(true);
827 m_Scripts.Clear();
828 lockScriptsForWrite(false);
829 m_PrimObjects.Clear();
830 m_Assemblies.Clear();
831 m_DomainScripts.Clear();
832
760 lock (m_ScriptEngines) 833 lock (m_ScriptEngines)
761 { 834 {
762 m_ScriptEngines.Remove(this); 835 m_ScriptEngines.Remove(this);
@@ -825,22 +898,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
825 898
826 List<IScriptInstance> instances = new List<IScriptInstance>(); 899 List<IScriptInstance> instances = new List<IScriptInstance>();
827 900
828 lock (m_Scripts) 901 lockScriptsForRead(true);
829 { 902 foreach (IScriptInstance instance in m_Scripts.Values)
830 foreach (IScriptInstance instance in m_Scripts.Values)
831 instances.Add(instance); 903 instances.Add(instance);
832 } 904 lockScriptsForRead(false);
833 905
834 foreach (IScriptInstance i in instances) 906 foreach (IScriptInstance i in instances)
835 { 907 {
836 string assembly = String.Empty; 908 string assembly = String.Empty;
837 909
838 lock (m_Scripts) 910
839 {
840 if (!m_Assemblies.ContainsKey(i.AssetID)) 911 if (!m_Assemblies.ContainsKey(i.AssetID))
841 continue; 912 continue;
842 assembly = m_Assemblies[i.AssetID]; 913 assembly = m_Assemblies[i.AssetID];
843 } 914
844 915
845 try 916 try
846 { 917 {
@@ -1244,97 +1315,126 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1244 } 1315 }
1245 1316
1246 ScriptInstance instance = null; 1317 ScriptInstance instance = null;
1247 lock (m_Scripts) 1318 // Create the object record
1248 { 1319 UUID appDomain = assetID;
1249 // Create the object record 1320
1250 if ((!m_Scripts.ContainsKey(itemID)) || 1321
1251 (m_Scripts[itemID].AssetID != assetID)) 1322
1323 lockScriptsForRead(true);
1324 if ((!m_Scripts.ContainsKey(itemID)) ||
1325 (m_Scripts[itemID].AssetID != assetID))
1326 {
1327 lockScriptsForRead(false);
1328 instance = new ScriptInstance(this, part,
1329 item,
1330 startParam, postOnRez,
1331 m_MaxScriptQueue);
1332
1333
1334
1335 if (part.ParentGroup.IsAttachment)
1336 appDomain = part.ParentGroup.RootPart.UUID;
1337
1338 if (!m_AppDomains.ContainsKey(appDomain))
1252 { 1339 {
1253 UUID appDomain = assetID; 1340 try
1254
1255 if (part.ParentGroup.IsAttachment)
1256 appDomain = part.ParentGroup.RootPart.UUID;
1257
1258 if (!m_AppDomains.ContainsKey(appDomain))
1259 { 1341 {
1260 try 1342 AppDomainSetup appSetup = new AppDomainSetup();
1261 { 1343 appSetup.PrivateBinPath = Path.Combine(
1262 AppDomainSetup appSetup = new AppDomainSetup(); 1344 m_ScriptEnginesPath,
1263 appSetup.PrivateBinPath = Path.Combine( 1345 m_Scene.RegionInfo.RegionID.ToString());
1264 m_ScriptEnginesPath,
1265 m_Scene.RegionInfo.RegionID.ToString());
1266 1346
1267 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 1347 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
1268 Evidence evidence = new Evidence(baseEvidence); 1348 Evidence evidence = new Evidence(baseEvidence);
1269 1349
1270 AppDomain sandbox; 1350 AppDomain sandbox;
1271 if (m_AppDomainLoading) 1351 if (m_AppDomainLoading)
1352 {
1353 sandbox = AppDomain.CreateDomain(
1354 m_Scene.RegionInfo.RegionID.ToString(),
1355 evidence, appSetup);
1356 if (m_AppDomains.ContainsKey(appDomain))
1272 { 1357 {
1273 sandbox = AppDomain.CreateDomain( 1358 m_AppDomains[appDomain].AssemblyResolve +=
1274 m_Scene.RegionInfo.RegionID.ToString(),
1275 evidence, appSetup);
1276 sandbox.AssemblyResolve +=
1277 new ResolveEventHandler( 1359 new ResolveEventHandler(
1278 AssemblyResolver.OnAssemblyResolve); 1360 AssemblyResolver.OnAssemblyResolve);
1361 if (m_DomainScripts.ContainsKey(appDomain))
1362 {
1363 m_DomainScripts[appDomain].Add(itemID);
1364 }
1365 else
1366 {
1367 m_DomainScripts.Add(appDomain, new List<UUID>());
1368 m_DomainScripts[appDomain].Add(itemID);
1369 }
1279 } 1370 }
1280 else 1371 else
1281 { 1372 {
1282 sandbox = AppDomain.CurrentDomain; 1373 m_AppDomains.Add(appDomain, sandbox);
1374 m_AppDomains[appDomain].AssemblyResolve +=
1375 new ResolveEventHandler(
1376 AssemblyResolver.OnAssemblyResolve);
1377 if (m_DomainScripts.ContainsKey(appDomain))
1378 {
1379 m_DomainScripts[appDomain].Add(itemID);
1380 }
1381 else
1382 {
1383 m_DomainScripts.Add(appDomain, new List<UUID>());
1384 m_DomainScripts[appDomain].Add(itemID);
1385 }
1386
1283 } 1387 }
1284
1285 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1286 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1287 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1288 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1289 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1290 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1291 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1292
1293 m_AppDomains[appDomain] = sandbox;
1294 1388
1295 m_DomainScripts[appDomain] = new List<UUID>();
1296 } 1389 }
1297 catch (Exception e) 1390 else
1298 { 1391 {
1299 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); 1392 sandbox = AppDomain.CurrentDomain;
1300 m_ScriptErrorMessage += "Exception creating app domain:\n";
1301 m_ScriptFailCount++;
1302 lock (m_AddingAssemblies)
1303 {
1304 m_AddingAssemblies[assembly]--;
1305 }
1306 return false;
1307 } 1393 }
1308 }
1309 m_DomainScripts[appDomain].Add(itemID);
1310
1311 instance = new ScriptInstance(this, part,
1312 item,
1313 startParam, postOnRez,
1314 m_MaxScriptQueue);
1315 1394
1316 if (!instance.Load(m_AppDomains[appDomain], assembly, stateSource)) 1395 if (!instance.Load(m_AppDomains[appDomain], assembly, stateSource))
1317 return false; 1396 return false;
1318 1397
1319// if (DebugLevel >= 1) 1398 m_AppDomains[appDomain] = sandbox;
1320// m_log.DebugFormat(
1321// "[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}",
1322// part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
1323// part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1324 1399
1325 if (presence != null) 1400 m_DomainScripts[appDomain] = new List<UUID>();
1401 }
1402 catch (Exception e)
1326 { 1403 {
1327 ShowScriptSaveResponse(item.OwnerID, 1404 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
1328 assetID, "Compile successful", true); 1405 m_ScriptErrorMessage += "Exception creating app domain:\n";
1406 m_ScriptFailCount++;
1407 lock (m_AddingAssemblies)
1408 {
1409 m_AddingAssemblies[assembly]--;
1410 }
1411 return false;
1329 } 1412 }
1413 }
1414
1330 1415
1331 instance.AppDomain = appDomain; 1416 instance.Load(m_AppDomains[appDomain], assembly, stateSource);
1332 instance.LineMap = linemap; 1417// m_log.DebugFormat(
1418// "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1419// part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
1420// part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1333 1421
1334 m_Scripts[itemID] = instance; 1422 if (presence != null)
1423 {
1424 ShowScriptSaveResponse(item.OwnerID,
1425 assetID, "Compile successful", true);
1335 } 1426 }
1336 }
1337 1427
1428 instance.AppDomain = appDomain;
1429 instance.LineMap = linemap;
1430 lockScriptsForWrite(true);
1431 m_Scripts[itemID] = instance;
1432 lockScriptsForWrite(false);
1433 }
1434 else
1435 {
1436 lockScriptsForRead(false);
1437 }
1338 lock (m_PrimObjects) 1438 lock (m_PrimObjects)
1339 { 1439 {
1340 if (!m_PrimObjects.ContainsKey(localID)) 1440 if (!m_PrimObjects.ContainsKey(localID))
@@ -1352,7 +1452,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1352 m_AddingAssemblies[assembly]--; 1452 m_AddingAssemblies[assembly]--;
1353 } 1453 }
1354 1454
1355 if (instance != null) 1455 if (instance!=null)
1356 instance.Init(); 1456 instance.Init();
1357 1457
1358 bool runIt; 1458 bool runIt;
@@ -1375,18 +1475,28 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1375 m_CompileDict.Remove(itemID); 1475 m_CompileDict.Remove(itemID);
1376 } 1476 }
1377 1477
1378 IScriptInstance instance = null; 1478 lockScriptsForRead(true);
1379 1479 // Do we even have it?
1380 lock (m_Scripts) 1480 if (!m_Scripts.ContainsKey(itemID))
1381 { 1481 {
1382 // Do we even have it? 1482 // Do we even have it?
1383 if (!m_Scripts.ContainsKey(itemID)) 1483 if (!m_Scripts.ContainsKey(itemID))
1384 return; 1484 return;
1385 1485
1386 instance = m_Scripts[itemID]; 1486 lockScriptsForRead(false);
1487 lockScriptsForWrite(true);
1387 m_Scripts.Remove(itemID); 1488 m_Scripts.Remove(itemID);
1489 lockScriptsForWrite(false);
1490
1491 return;
1388 } 1492 }
1493
1389 1494
1495 IScriptInstance instance=m_Scripts[itemID];
1496 lockScriptsForRead(false);
1497 lockScriptsForWrite(true);
1498 m_Scripts.Remove(itemID);
1499 lockScriptsForWrite(false);
1390 instance.ClearQueue(); 1500 instance.ClearQueue();
1391 1501
1392 instance.Stop(m_WaitForEventCompletionOnScriptStop); 1502 instance.Stop(m_WaitForEventCompletionOnScriptStop);
@@ -1423,8 +1533,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1423 1533
1424 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 1534 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
1425 if (handlerObjectRemoved != null) 1535 if (handlerObjectRemoved != null)
1426 handlerObjectRemoved(instance.ObjectID); 1536 {
1537 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
1538 if (part != null)
1539 handlerObjectRemoved(part.UUID);
1540 }
1427 1541
1542 CleanAssemblies();
1543
1428 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 1544 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
1429 if (handlerScriptRemoved != null) 1545 if (handlerScriptRemoved != null)
1430 handlerScriptRemoved(itemID); 1546 handlerScriptRemoved(itemID);
@@ -1685,12 +1801,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1685 private IScriptInstance GetInstance(UUID itemID) 1801 private IScriptInstance GetInstance(UUID itemID)
1686 { 1802 {
1687 IScriptInstance instance; 1803 IScriptInstance instance;
1688 lock (m_Scripts) 1804 lockScriptsForRead(true);
1805 if (!m_Scripts.ContainsKey(itemID))
1689 { 1806 {
1690 if (!m_Scripts.ContainsKey(itemID)) 1807 lockScriptsForRead(false);
1691 return null; 1808 return null;
1692 instance = m_Scripts[itemID];
1693 } 1809 }
1810 instance = m_Scripts[itemID];
1811 lockScriptsForRead(false);
1694 return instance; 1812 return instance;
1695 } 1813 }
1696 1814
@@ -1714,6 +1832,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1714 return false; 1832 return false;
1715 } 1833 }
1716 1834
1835 [DebuggerNonUserCode]
1717 public void ApiResetScript(UUID itemID) 1836 public void ApiResetScript(UUID itemID)
1718 { 1837 {
1719 IScriptInstance instance = GetInstance(itemID); 1838 IScriptInstance instance = GetInstance(itemID);
@@ -1775,6 +1894,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1775 return UUID.Zero; 1894 return UUID.Zero;
1776 } 1895 }
1777 1896
1897 [DebuggerNonUserCode]
1778 public void SetState(UUID itemID, string newState) 1898 public void SetState(UUID itemID, string newState)
1779 { 1899 {
1780 IScriptInstance instance = GetInstance(itemID); 1900 IScriptInstance instance = GetInstance(itemID);
@@ -1797,11 +1917,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1797 1917
1798 List<IScriptInstance> instances = new List<IScriptInstance>(); 1918 List<IScriptInstance> instances = new List<IScriptInstance>();
1799 1919
1800 lock (m_Scripts) 1920 lockScriptsForRead(true);
1801 { 1921 foreach (IScriptInstance instance in m_Scripts.Values)
1802 foreach (IScriptInstance instance in m_Scripts.Values)
1803 instances.Add(instance); 1922 instances.Add(instance);
1804 } 1923 lockScriptsForRead(false);
1805 1924
1806 foreach (IScriptInstance i in instances) 1925 foreach (IScriptInstance i in instances)
1807 { 1926 {