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 8c3bb5b..34fcf0c 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 private ScriptEngineConsoleCommands m_consoleCommands; 240 private ScriptEngineConsoleCommands m_consoleCommands;
173 241
174 public string ScriptEngineName 242 public string ScriptEngineName
@@ -677,64 +745,69 @@ namespace OpenSim.Region.ScriptEngine.XEngine
677 { 745 {
678 if (!m_Enabled) 746 if (!m_Enabled)
679 return; 747 return;
748 lockScriptsForRead(true);
680 749
681 lock (m_Scripts) 750 List<IScriptInstance> instancesToDel = new List<IScriptInstance>(m_Scripts.Values);
682 {
683 m_log.InfoFormat(
684 "[XEngine]: Shutting down {0} scripts in {1}", m_Scripts.Count, m_Scene.RegionInfo.RegionName);
685 751
686 foreach (IScriptInstance instance in m_Scripts.Values) 752// foreach (IScriptInstance instance in m_Scripts.Values)
753 foreach (IScriptInstance instance in instancesToDel)
754 {
755 // Force a final state save
756 //
757 if (m_Assemblies.ContainsKey(instance.AssetID))
687 { 758 {
688 // Force a final state save 759 string assembly = m_Assemblies[instance.AssetID];
689 //
690 if (m_Assemblies.ContainsKey(instance.AssetID))
691 {
692 string assembly = m_Assemblies[instance.AssetID];
693 760
694 try 761 try
695 { 762 {
696 instance.SaveState(assembly); 763 instance.SaveState(assembly);
697 }
698 catch (Exception e)
699 {
700 m_log.Error(
701 string.Format(
702 "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ",
703 instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name)
704 , e);
705 }
706 } 764 }
765 catch (Exception e)
766 {
767 m_log.Error(
768 string.Format(
769 "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ",
770 instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name)
771 , e);
772 }
773 }
707 774
708 // Clear the event queue and abort the instance thread 775 // Clear the event queue and abort the instance thread
709 // 776 //
710 instance.ClearQueue(); 777 instance.ClearQueue();
711 instance.Stop(0); 778 instance.Stop(0);
712 779
713 // Release events, timer, etc 780 // Release events, timer, etc
714 // 781 //
715 instance.DestroyScriptInstance(); 782 instance.DestroyScriptInstance();
716 783
717 // Unload scripts and app domains. 784 // Unload scripts and app domains
718 // Must be done explicitly because they have infinite 785 // Must be done explicitly because they have infinite
719 // lifetime. 786 // lifetime
720 // However, don't bother to do this if the simulator is shutting 787 //
721 // down since it takes a long time with many scripts. 788// if (!m_SimulatorShuttingDown)
722 if (!m_SimulatorShuttingDown) 789 {
790 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
791 if (m_DomainScripts[instance.AppDomain].Count == 0)
723 { 792 {
724 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 793 m_DomainScripts.Remove(instance.AppDomain);
725 if (m_DomainScripts[instance.AppDomain].Count == 0) 794 UnloadAppDomain(instance.AppDomain);
726 {
727 m_DomainScripts.Remove(instance.AppDomain);
728 UnloadAppDomain(instance.AppDomain);
729 }
730 } 795 }
731 } 796 }
732 797
733 m_Scripts.Clear(); 798// m_Scripts.Clear();
734 m_PrimObjects.Clear(); 799// m_PrimObjects.Clear();
735 m_Assemblies.Clear(); 800// m_Assemblies.Clear();
736 m_DomainScripts.Clear(); 801// m_DomainScripts.Clear();
737 } 802 }
803 lockScriptsForRead(false);
804 lockScriptsForWrite(true);
805 m_Scripts.Clear();
806 lockScriptsForWrite(false);
807 m_PrimObjects.Clear();
808 m_Assemblies.Clear();
809 m_DomainScripts.Clear();
810
738 lock (m_ScriptEngines) 811 lock (m_ScriptEngines)
739 { 812 {
740 m_ScriptEngines.Remove(this); 813 m_ScriptEngines.Remove(this);
@@ -803,22 +876,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
803 876
804 List<IScriptInstance> instances = new List<IScriptInstance>(); 877 List<IScriptInstance> instances = new List<IScriptInstance>();
805 878
806 lock (m_Scripts) 879 lockScriptsForRead(true);
807 { 880 foreach (IScriptInstance instance in m_Scripts.Values)
808 foreach (IScriptInstance instance in m_Scripts.Values)
809 instances.Add(instance); 881 instances.Add(instance);
810 } 882 lockScriptsForRead(false);
811 883
812 foreach (IScriptInstance i in instances) 884 foreach (IScriptInstance i in instances)
813 { 885 {
814 string assembly = String.Empty; 886 string assembly = String.Empty;
815 887
816 lock (m_Scripts) 888
817 {
818 if (!m_Assemblies.ContainsKey(i.AssetID)) 889 if (!m_Assemblies.ContainsKey(i.AssetID))
819 continue; 890 continue;
820 assembly = m_Assemblies[i.AssetID]; 891 assembly = m_Assemblies[i.AssetID];
821 } 892
822 893
823 try 894 try
824 { 895 {
@@ -1219,96 +1290,99 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1219 } 1290 }
1220 1291
1221 ScriptInstance instance = null; 1292 ScriptInstance instance = null;
1222 lock (m_Scripts) 1293 // Create the object record
1294 lockScriptsForRead(true);
1295 if ((!m_Scripts.ContainsKey(itemID)) ||
1296 (m_Scripts[itemID].AssetID != assetID))
1223 { 1297 {
1224 // Create the object record 1298 lockScriptsForRead(false);
1225 if ((!m_Scripts.ContainsKey(itemID)) ||
1226 (m_Scripts[itemID].AssetID != assetID))
1227 {
1228 UUID appDomain = assetID;
1229 1299
1230 if (part.ParentGroup.IsAttachment) 1300 UUID appDomain = assetID;
1231 appDomain = part.ParentGroup.RootPart.UUID;
1232 1301
1233 if (!m_AppDomains.ContainsKey(appDomain)) 1302 if (part.ParentGroup.IsAttachment)
1234 { 1303 appDomain = part.ParentGroup.RootPart.UUID;
1235 try
1236 {
1237 AppDomainSetup appSetup = new AppDomainSetup();
1238 appSetup.PrivateBinPath = Path.Combine(
1239 m_ScriptEnginesPath,
1240 m_Scene.RegionInfo.RegionID.ToString());
1241 1304
1242 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 1305 if (!m_AppDomains.ContainsKey(appDomain))
1243 Evidence evidence = new Evidence(baseEvidence); 1306 {
1307 try
1308 {
1309 AppDomainSetup appSetup = new AppDomainSetup();
1310 appSetup.PrivateBinPath = Path.Combine(
1311 m_ScriptEnginesPath,
1312 m_Scene.RegionInfo.RegionID.ToString());
1244 1313
1245 AppDomain sandbox; 1314 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
1246 if (m_AppDomainLoading) 1315 Evidence evidence = new Evidence(baseEvidence);
1247 {
1248 sandbox = AppDomain.CreateDomain(
1249 m_Scene.RegionInfo.RegionID.ToString(),
1250 evidence, appSetup);
1251 sandbox.AssemblyResolve +=
1252 new ResolveEventHandler(
1253 AssemblyResolver.OnAssemblyResolve);
1254 }
1255 else
1256 {
1257 sandbox = AppDomain.CurrentDomain;
1258 }
1259
1260 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1261 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1262 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1263 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1264 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1265 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1266 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1267
1268 m_AppDomains[appDomain] = sandbox;
1269 1316
1270 m_DomainScripts[appDomain] = new List<UUID>(); 1317 AppDomain sandbox;
1318 if (m_AppDomainLoading)
1319 {
1320 sandbox = AppDomain.CreateDomain(
1321 m_Scene.RegionInfo.RegionID.ToString(),
1322 evidence, appSetup);
1323 m_AppDomains[appDomain].AssemblyResolve +=
1324 new ResolveEventHandler(
1325 AssemblyResolver.OnAssemblyResolve);
1271 } 1326 }
1272 catch (Exception e) 1327 else
1273 { 1328 {
1274 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); 1329 sandbox = AppDomain.CurrentDomain;
1275 m_ScriptErrorMessage += "Exception creating app domain:\n";
1276 m_ScriptFailCount++;
1277 lock (m_AddingAssemblies)
1278 {
1279 m_AddingAssemblies[assembly]--;
1280 }
1281 return false;
1282 } 1330 }
1283 }
1284 m_DomainScripts[appDomain].Add(itemID);
1285
1286 instance = new ScriptInstance(this, part,
1287 itemID, assetID, assembly,
1288 m_AppDomains[appDomain],
1289 part.ParentGroup.RootPart.Name,
1290 item.Name, startParam, postOnRez,
1291 stateSource, m_MaxScriptQueue);
1292
1293// if (DebugLevel >= 1)
1294// m_log.DebugFormat(
1295// "[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}",
1296// part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
1297// part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1298 1331
1299 if (presence != null) 1332 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1333 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1334 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1335 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1336 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1337 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1338 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1339
1340 m_AppDomains[appDomain] = sandbox;
1341
1342 m_DomainScripts[appDomain] = new List<UUID>();
1343 }
1344 catch (Exception e)
1300 { 1345 {
1301 ShowScriptSaveResponse(item.OwnerID, 1346 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
1302 assetID, "Compile successful", true); 1347 m_ScriptErrorMessage += "Exception creating app domain:\n";
1348 m_ScriptFailCount++;
1349 lock (m_AddingAssemblies)
1350 {
1351 m_AddingAssemblies[assembly]--;
1352 }
1353 return false;
1303 } 1354 }
1355 }
1356 m_DomainScripts[appDomain].Add(itemID);
1357
1358 instance = new ScriptInstance(this, part,
1359 itemID, assetID, assembly,
1360 m_AppDomains[appDomain],
1361 part.ParentGroup.RootPart.Name,
1362 item.Name, startParam, postOnRez,
1363 stateSource, m_MaxScriptQueue);
1364
1365// m_log.DebugFormat(
1366// "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1367// part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
1368// part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1304 1369
1305 instance.AppDomain = appDomain; 1370 if (presence != null)
1306 instance.LineMap = linemap; 1371 {
1307 1372 ShowScriptSaveResponse(item.OwnerID,
1308 m_Scripts[itemID] = instance; 1373 assetID, "Compile successful", true);
1309 } 1374 }
1310 }
1311 1375
1376 instance.AppDomain = appDomain;
1377 instance.LineMap = linemap;
1378 lockScriptsForWrite(true);
1379 m_Scripts[itemID] = instance;
1380 lockScriptsForWrite(false);
1381 }
1382 else
1383 {
1384 lockScriptsForRead(false);
1385 }
1312 lock (m_PrimObjects) 1386 lock (m_PrimObjects)
1313 { 1387 {
1314 if (!m_PrimObjects.ContainsKey(localID)) 1388 if (!m_PrimObjects.ContainsKey(localID))
@@ -1326,7 +1400,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1326 m_AddingAssemblies[assembly]--; 1400 m_AddingAssemblies[assembly]--;
1327 } 1401 }
1328 1402
1329 if (instance != null) 1403 if (instance!=null)
1330 instance.Init(); 1404 instance.Init();
1331 1405
1332 bool runIt; 1406 bool runIt;
@@ -1349,18 +1423,28 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1349 m_CompileDict.Remove(itemID); 1423 m_CompileDict.Remove(itemID);
1350 } 1424 }
1351 1425
1352 IScriptInstance instance = null; 1426 lockScriptsForRead(true);
1353 1427 // Do we even have it?
1354 lock (m_Scripts) 1428 if (!m_Scripts.ContainsKey(itemID))
1355 { 1429 {
1356 // Do we even have it? 1430 // Do we even have it?
1357 if (!m_Scripts.ContainsKey(itemID)) 1431 if (!m_Scripts.ContainsKey(itemID))
1358 return; 1432 return;
1359 1433
1360 instance = m_Scripts[itemID]; 1434 lockScriptsForRead(false);
1435 lockScriptsForWrite(true);
1361 m_Scripts.Remove(itemID); 1436 m_Scripts.Remove(itemID);
1437 lockScriptsForWrite(false);
1438
1439 return;
1362 } 1440 }
1441
1363 1442
1443 IScriptInstance instance=m_Scripts[itemID];
1444 lockScriptsForRead(false);
1445 lockScriptsForWrite(true);
1446 m_Scripts.Remove(itemID);
1447 lockScriptsForWrite(false);
1364 instance.ClearQueue(); 1448 instance.ClearQueue();
1365 1449
1366 instance.Stop(m_WaitForEventCompletionOnScriptStop); 1450 instance.Stop(m_WaitForEventCompletionOnScriptStop);
@@ -1397,8 +1481,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1397 1481
1398 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 1482 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
1399 if (handlerObjectRemoved != null) 1483 if (handlerObjectRemoved != null)
1400 handlerObjectRemoved(instance.ObjectID); 1484 {
1485 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
1486 handlerObjectRemoved(part.UUID);
1487 }
1401 1488
1489 CleanAssemblies();
1490
1402 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 1491 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
1403 if (handlerScriptRemoved != null) 1492 if (handlerScriptRemoved != null)
1404 handlerScriptRemoved(itemID); 1493 handlerScriptRemoved(itemID);
@@ -1659,12 +1748,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1659 private IScriptInstance GetInstance(UUID itemID) 1748 private IScriptInstance GetInstance(UUID itemID)
1660 { 1749 {
1661 IScriptInstance instance; 1750 IScriptInstance instance;
1662 lock (m_Scripts) 1751 lockScriptsForRead(true);
1752 if (!m_Scripts.ContainsKey(itemID))
1663 { 1753 {
1664 if (!m_Scripts.ContainsKey(itemID)) 1754 lockScriptsForRead(false);
1665 return null; 1755 return null;
1666 instance = m_Scripts[itemID];
1667 } 1756 }
1757 instance = m_Scripts[itemID];
1758 lockScriptsForRead(false);
1668 return instance; 1759 return instance;
1669 } 1760 }
1670 1761
@@ -1688,6 +1779,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1688 return false; 1779 return false;
1689 } 1780 }
1690 1781
1782 [DebuggerNonUserCode]
1691 public void ApiResetScript(UUID itemID) 1783 public void ApiResetScript(UUID itemID)
1692 { 1784 {
1693 IScriptInstance instance = GetInstance(itemID); 1785 IScriptInstance instance = GetInstance(itemID);
@@ -1744,6 +1836,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1744 return UUID.Zero; 1836 return UUID.Zero;
1745 } 1837 }
1746 1838
1839 [DebuggerNonUserCode]
1747 public void SetState(UUID itemID, string newState) 1840 public void SetState(UUID itemID, string newState)
1748 { 1841 {
1749 IScriptInstance instance = GetInstance(itemID); 1842 IScriptInstance instance = GetInstance(itemID);
@@ -1766,11 +1859,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1766 1859
1767 List<IScriptInstance> instances = new List<IScriptInstance>(); 1860 List<IScriptInstance> instances = new List<IScriptInstance>();
1768 1861
1769 lock (m_Scripts) 1862 lockScriptsForRead(true);
1770 { 1863 foreach (IScriptInstance instance in m_Scripts.Values)
1771 foreach (IScriptInstance instance in m_Scripts.Values)
1772 instances.Add(instance); 1864 instances.Add(instance);
1773 } 1865 lockScriptsForRead(false);
1774 1866
1775 foreach (IScriptInstance i in instances) 1867 foreach (IScriptInstance i in instances)
1776 { 1868 {