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.cs378
1 files changed, 235 insertions, 143 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index f38d17d..0bd9a06 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;
@@ -147,6 +148,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
147 private Dictionary<UUID, IScriptInstance> m_Scripts = 148 private Dictionary<UUID, IScriptInstance> m_Scripts =
148 new Dictionary<UUID, IScriptInstance>(); 149 new Dictionary<UUID, IScriptInstance>();
149 150
151 private OpenMetaverse.ReaderWriterLockSlim m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
152
150 // Maps the asset ID to the assembly 153 // Maps the asset ID to the assembly
151 154
152 private Dictionary<UUID, string> m_Assemblies = 155 private Dictionary<UUID, string> m_Assemblies =
@@ -169,6 +172,71 @@ namespace OpenSim.Region.ScriptEngine.XEngine
169 IWorkItemResult m_CurrentCompile = null; 172 IWorkItemResult m_CurrentCompile = null;
170 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>(); 173 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>();
171 174
175 private void lockScriptsForRead(bool locked)
176 {
177 if (locked)
178 {
179 if (m_scriptsLock.RecursiveReadCount > 0)
180 {
181 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.");
182 m_scriptsLock.ExitReadLock();
183 }
184 if (m_scriptsLock.RecursiveWriteCount > 0)
185 {
186 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
187 m_scriptsLock.ExitWriteLock();
188 }
189
190 while (!m_scriptsLock.TryEnterReadLock(60000))
191 {
192 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.");
193 if (m_scriptsLock.IsWriteLockHeld)
194 {
195 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
196 }
197 }
198 }
199 else
200 {
201 if (m_scriptsLock.RecursiveReadCount > 0)
202 {
203 m_scriptsLock.ExitReadLock();
204 }
205 }
206 }
207 private void lockScriptsForWrite(bool locked)
208 {
209 if (locked)
210 {
211 if (m_scriptsLock.RecursiveReadCount > 0)
212 {
213 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.");
214 m_scriptsLock.ExitReadLock();
215 }
216 if (m_scriptsLock.RecursiveWriteCount > 0)
217 {
218 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
219 m_scriptsLock.ExitWriteLock();
220 }
221
222 while (!m_scriptsLock.TryEnterWriteLock(60000))
223 {
224 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.");
225 if (m_scriptsLock.IsWriteLockHeld)
226 {
227 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
228 }
229 }
230 }
231 else
232 {
233 if (m_scriptsLock.RecursiveWriteCount > 0)
234 {
235 m_scriptsLock.ExitWriteLock();
236 }
237 }
238 }
239
172 public string ScriptEngineName 240 public string ScriptEngineName
173 { 241 {
174 get { return "XEngine"; } 242 get { return "XEngine"; }
@@ -670,64 +738,69 @@ namespace OpenSim.Region.ScriptEngine.XEngine
670 { 738 {
671 if (!m_Enabled) 739 if (!m_Enabled)
672 return; 740 return;
741 lockScriptsForRead(true);
673 742
674 lock (m_Scripts) 743 List<IScriptInstance> instancesToDel = new List<IScriptInstance>(m_Scripts.Values);
675 {
676 m_log.InfoFormat(
677 "[XEngine]: Shutting down {0} scripts in {1}", m_Scripts.Count, m_Scene.RegionInfo.RegionName);
678 744
679 foreach (IScriptInstance instance in m_Scripts.Values) 745// foreach (IScriptInstance instance in m_Scripts.Values)
746 foreach (IScriptInstance instance in instancesToDel)
747 {
748 // Force a final state save
749 //
750 if (m_Assemblies.ContainsKey(instance.AssetID))
680 { 751 {
681 // Force a final state save 752 string assembly = m_Assemblies[instance.AssetID];
682 //
683 if (m_Assemblies.ContainsKey(instance.AssetID))
684 {
685 string assembly = m_Assemblies[instance.AssetID];
686 753
687 try 754 try
688 { 755 {
689 instance.SaveState(assembly); 756 instance.SaveState(assembly);
690 }
691 catch (Exception e)
692 {
693 m_log.Error(
694 string.Format(
695 "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ",
696 instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name)
697 , e);
698 }
699 } 757 }
758 catch (Exception e)
759 {
760 m_log.Error(
761 string.Format(
762 "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ",
763 instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name)
764 , e);
765 }
766 }
700 767
701 // Clear the event queue and abort the instance thread 768 // Clear the event queue and abort the instance thread
702 // 769 //
703 instance.ClearQueue(); 770 instance.ClearQueue();
704 instance.Stop(0); 771 instance.Stop(0);
705 772
706 // Release events, timer, etc 773 // Release events, timer, etc
707 // 774 //
708 instance.DestroyScriptInstance(); 775 instance.DestroyScriptInstance();
709 776
710 // Unload scripts and app domains. 777 // Unload scripts and app domains
711 // Must be done explicitly because they have infinite 778 // Must be done explicitly because they have infinite
712 // lifetime. 779 // lifetime
713 // However, don't bother to do this if the simulator is shutting 780 //
714 // down since it takes a long time with many scripts. 781// if (!m_SimulatorShuttingDown)
715 if (!m_SimulatorShuttingDown) 782 {
783 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
784 if (m_DomainScripts[instance.AppDomain].Count == 0)
716 { 785 {
717 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 786 m_DomainScripts.Remove(instance.AppDomain);
718 if (m_DomainScripts[instance.AppDomain].Count == 0) 787 UnloadAppDomain(instance.AppDomain);
719 {
720 m_DomainScripts.Remove(instance.AppDomain);
721 UnloadAppDomain(instance.AppDomain);
722 }
723 } 788 }
724 } 789 }
725 790
726 m_Scripts.Clear(); 791// m_Scripts.Clear();
727 m_PrimObjects.Clear(); 792// m_PrimObjects.Clear();
728 m_Assemblies.Clear(); 793// m_Assemblies.Clear();
729 m_DomainScripts.Clear(); 794// m_DomainScripts.Clear();
730 } 795 }
796 lockScriptsForRead(false);
797 lockScriptsForWrite(true);
798 m_Scripts.Clear();
799 lockScriptsForWrite(false);
800 m_PrimObjects.Clear();
801 m_Assemblies.Clear();
802 m_DomainScripts.Clear();
803
731 lock (m_ScriptEngines) 804 lock (m_ScriptEngines)
732 { 805 {
733 m_ScriptEngines.Remove(this); 806 m_ScriptEngines.Remove(this);
@@ -796,22 +869,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
796 869
797 List<IScriptInstance> instances = new List<IScriptInstance>(); 870 List<IScriptInstance> instances = new List<IScriptInstance>();
798 871
799 lock (m_Scripts) 872 lockScriptsForRead(true);
800 { 873 foreach (IScriptInstance instance in m_Scripts.Values)
801 foreach (IScriptInstance instance in m_Scripts.Values)
802 instances.Add(instance); 874 instances.Add(instance);
803 } 875 lockScriptsForRead(false);
804 876
805 foreach (IScriptInstance i in instances) 877 foreach (IScriptInstance i in instances)
806 { 878 {
807 string assembly = String.Empty; 879 string assembly = String.Empty;
808 880
809 lock (m_Scripts) 881
810 {
811 if (!m_Assemblies.ContainsKey(i.AssetID)) 882 if (!m_Assemblies.ContainsKey(i.AssetID))
812 continue; 883 continue;
813 assembly = m_Assemblies[i.AssetID]; 884 assembly = m_Assemblies[i.AssetID];
814 } 885
815 886
816 try 887 try
817 { 888 {
@@ -1212,96 +1283,99 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1212 } 1283 }
1213 1284
1214 ScriptInstance instance = null; 1285 ScriptInstance instance = null;
1215 lock (m_Scripts) 1286 // Create the object record
1287 lockScriptsForRead(true);
1288 if ((!m_Scripts.ContainsKey(itemID)) ||
1289 (m_Scripts[itemID].AssetID != assetID))
1216 { 1290 {
1217 // Create the object record 1291 lockScriptsForRead(false);
1218 if ((!m_Scripts.ContainsKey(itemID)) ||
1219 (m_Scripts[itemID].AssetID != assetID))
1220 {
1221 UUID appDomain = assetID;
1222 1292
1223 if (part.ParentGroup.IsAttachment) 1293 UUID appDomain = assetID;
1224 appDomain = part.ParentGroup.RootPart.UUID;
1225 1294
1226 if (!m_AppDomains.ContainsKey(appDomain)) 1295 if (part.ParentGroup.IsAttachment)
1227 { 1296 appDomain = part.ParentGroup.RootPart.UUID;
1228 try
1229 {
1230 AppDomainSetup appSetup = new AppDomainSetup();
1231 appSetup.PrivateBinPath = Path.Combine(
1232 m_ScriptEnginesPath,
1233 m_Scene.RegionInfo.RegionID.ToString());
1234 1297
1235 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 1298 if (!m_AppDomains.ContainsKey(appDomain))
1236 Evidence evidence = new Evidence(baseEvidence); 1299 {
1300 try
1301 {
1302 AppDomainSetup appSetup = new AppDomainSetup();
1303 appSetup.PrivateBinPath = Path.Combine(
1304 m_ScriptEnginesPath,
1305 m_Scene.RegionInfo.RegionID.ToString());
1237 1306
1238 AppDomain sandbox; 1307 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
1239 if (m_AppDomainLoading) 1308 Evidence evidence = new Evidence(baseEvidence);
1240 {
1241 sandbox = AppDomain.CreateDomain(
1242 m_Scene.RegionInfo.RegionID.ToString(),
1243 evidence, appSetup);
1244 sandbox.AssemblyResolve +=
1245 new ResolveEventHandler(
1246 AssemblyResolver.OnAssemblyResolve);
1247 }
1248 else
1249 {
1250 sandbox = AppDomain.CurrentDomain;
1251 }
1252
1253 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1254 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1255 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1256 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1257 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1258 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1259 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1260
1261 m_AppDomains[appDomain] = sandbox;
1262 1309
1263 m_DomainScripts[appDomain] = new List<UUID>(); 1310 AppDomain sandbox;
1311 if (m_AppDomainLoading)
1312 {
1313 sandbox = AppDomain.CreateDomain(
1314 m_Scene.RegionInfo.RegionID.ToString(),
1315 evidence, appSetup);
1316 m_AppDomains[appDomain].AssemblyResolve +=
1317 new ResolveEventHandler(
1318 AssemblyResolver.OnAssemblyResolve);
1264 } 1319 }
1265 catch (Exception e) 1320 else
1266 { 1321 {
1267 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); 1322 sandbox = AppDomain.CurrentDomain;
1268 m_ScriptErrorMessage += "Exception creating app domain:\n";
1269 m_ScriptFailCount++;
1270 lock (m_AddingAssemblies)
1271 {
1272 m_AddingAssemblies[assembly]--;
1273 }
1274 return false;
1275 } 1323 }
1276 }
1277 m_DomainScripts[appDomain].Add(itemID);
1278
1279 instance = new ScriptInstance(this, part,
1280 itemID, assetID, assembly,
1281 m_AppDomains[appDomain],
1282 part.ParentGroup.RootPart.Name,
1283 item.Name, startParam, postOnRez,
1284 stateSource, m_MaxScriptQueue);
1285
1286// if (DebugLevel >= 1)
1287// m_log.DebugFormat(
1288// "[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}",
1289// part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
1290// part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1291 1324
1292 if (presence != null) 1325 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1326 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1327 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1328 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1329 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1330 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1331 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1332
1333 m_AppDomains[appDomain] = sandbox;
1334
1335 m_DomainScripts[appDomain] = new List<UUID>();
1336 }
1337 catch (Exception e)
1293 { 1338 {
1294 ShowScriptSaveResponse(item.OwnerID, 1339 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
1295 assetID, "Compile successful", true); 1340 m_ScriptErrorMessage += "Exception creating app domain:\n";
1341 m_ScriptFailCount++;
1342 lock (m_AddingAssemblies)
1343 {
1344 m_AddingAssemblies[assembly]--;
1345 }
1346 return false;
1296 } 1347 }
1348 }
1349 m_DomainScripts[appDomain].Add(itemID);
1350
1351 instance = new ScriptInstance(this, part,
1352 itemID, assetID, assembly,
1353 m_AppDomains[appDomain],
1354 part.ParentGroup.RootPart.Name,
1355 item.Name, startParam, postOnRez,
1356 stateSource, m_MaxScriptQueue);
1357
1358// m_log.DebugFormat(
1359// "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1360// part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
1361// part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1297 1362
1298 instance.AppDomain = appDomain; 1363 if (presence != null)
1299 instance.LineMap = linemap; 1364 {
1300 1365 ShowScriptSaveResponse(item.OwnerID,
1301 m_Scripts[itemID] = instance; 1366 assetID, "Compile successful", true);
1302 } 1367 }
1303 }
1304 1368
1369 instance.AppDomain = appDomain;
1370 instance.LineMap = linemap;
1371 lockScriptsForWrite(true);
1372 m_Scripts[itemID] = instance;
1373 lockScriptsForWrite(false);
1374 }
1375 else
1376 {
1377 lockScriptsForRead(false);
1378 }
1305 lock (m_PrimObjects) 1379 lock (m_PrimObjects)
1306 { 1380 {
1307 if (!m_PrimObjects.ContainsKey(localID)) 1381 if (!m_PrimObjects.ContainsKey(localID))
@@ -1319,7 +1393,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1319 m_AddingAssemblies[assembly]--; 1393 m_AddingAssemblies[assembly]--;
1320 } 1394 }
1321 1395
1322 if (instance != null) 1396 if (instance!=null)
1323 instance.Init(); 1397 instance.Init();
1324 1398
1325 bool runIt; 1399 bool runIt;
@@ -1342,18 +1416,28 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1342 m_CompileDict.Remove(itemID); 1416 m_CompileDict.Remove(itemID);
1343 } 1417 }
1344 1418
1345 IScriptInstance instance = null; 1419 lockScriptsForRead(true);
1346 1420 // Do we even have it?
1347 lock (m_Scripts) 1421 if (!m_Scripts.ContainsKey(itemID))
1348 { 1422 {
1349 // Do we even have it? 1423 // Do we even have it?
1350 if (!m_Scripts.ContainsKey(itemID)) 1424 if (!m_Scripts.ContainsKey(itemID))
1351 return; 1425 return;
1352 1426
1353 instance = m_Scripts[itemID]; 1427 lockScriptsForRead(false);
1428 lockScriptsForWrite(true);
1354 m_Scripts.Remove(itemID); 1429 m_Scripts.Remove(itemID);
1430 lockScriptsForWrite(false);
1431
1432 return;
1355 } 1433 }
1434
1356 1435
1436 IScriptInstance instance=m_Scripts[itemID];
1437 lockScriptsForRead(false);
1438 lockScriptsForWrite(true);
1439 m_Scripts.Remove(itemID);
1440 lockScriptsForWrite(false);
1357 instance.ClearQueue(); 1441 instance.ClearQueue();
1358 1442
1359 instance.Stop(m_WaitForEventCompletionOnScriptStop); 1443 instance.Stop(m_WaitForEventCompletionOnScriptStop);
@@ -1390,8 +1474,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1390 1474
1391 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 1475 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
1392 if (handlerObjectRemoved != null) 1476 if (handlerObjectRemoved != null)
1393 handlerObjectRemoved(instance.ObjectID); 1477 {
1478 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
1479 handlerObjectRemoved(part.UUID);
1480 }
1394 1481
1482 CleanAssemblies();
1483
1395 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 1484 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
1396 if (handlerScriptRemoved != null) 1485 if (handlerScriptRemoved != null)
1397 handlerScriptRemoved(itemID); 1486 handlerScriptRemoved(itemID);
@@ -1651,12 +1740,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1651 private IScriptInstance GetInstance(UUID itemID) 1740 private IScriptInstance GetInstance(UUID itemID)
1652 { 1741 {
1653 IScriptInstance instance; 1742 IScriptInstance instance;
1654 lock (m_Scripts) 1743 lockScriptsForRead(true);
1744 if (!m_Scripts.ContainsKey(itemID))
1655 { 1745 {
1656 if (!m_Scripts.ContainsKey(itemID)) 1746 lockScriptsForRead(false);
1657 return null; 1747 return null;
1658 instance = m_Scripts[itemID];
1659 } 1748 }
1749 instance = m_Scripts[itemID];
1750 lockScriptsForRead(false);
1660 return instance; 1751 return instance;
1661 } 1752 }
1662 1753
@@ -1680,6 +1771,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1680 return false; 1771 return false;
1681 } 1772 }
1682 1773
1774 [DebuggerNonUserCode]
1683 public void ApiResetScript(UUID itemID) 1775 public void ApiResetScript(UUID itemID)
1684 { 1776 {
1685 IScriptInstance instance = GetInstance(itemID); 1777 IScriptInstance instance = GetInstance(itemID);
@@ -1736,6 +1828,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1736 return UUID.Zero; 1828 return UUID.Zero;
1737 } 1829 }
1738 1830
1831 [DebuggerNonUserCode]
1739 public void SetState(UUID itemID, string newState) 1832 public void SetState(UUID itemID, string newState)
1740 { 1833 {
1741 IScriptInstance instance = GetInstance(itemID); 1834 IScriptInstance instance = GetInstance(itemID);
@@ -1758,11 +1851,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1758 1851
1759 List<IScriptInstance> instances = new List<IScriptInstance>(); 1852 List<IScriptInstance> instances = new List<IScriptInstance>();
1760 1853
1761 lock (m_Scripts) 1854 lockScriptsForRead(true);
1762 { 1855 foreach (IScriptInstance instance in m_Scripts.Values)
1763 foreach (IScriptInstance instance in m_Scripts.Values)
1764 instances.Add(instance); 1856 instances.Add(instance);
1765 } 1857 lockScriptsForRead(false);
1766 1858
1767 foreach (IScriptInstance i in instances) 1859 foreach (IScriptInstance i in instances)
1768 { 1860 {