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.cs371
1 files changed, 231 insertions, 140 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 72646f6..816d8ba 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,98 @@ 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 item,
1288 startParam, postOnRez,
1289 m_MaxScriptQueue);
1290 1331
1291 instance.Load(m_AppDomains[appDomain], assembly, stateSource); 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);
1292 1339
1293// if (DebugLevel >= 1) 1340 m_AppDomains[appDomain] = sandbox;
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 1341
1299 if (presence != null) 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 item,
1360 startParam, postOnRez,
1361 m_MaxScriptQueue);
1304 1362
1305 instance.AppDomain = appDomain; 1363 instance.Load(m_AppDomains[appDomain], assembly, stateSource);
1306 instance.LineMap = linemap; 1364// m_log.DebugFormat(
1365// "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1366// part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
1367// part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1307 1368
1308 m_Scripts[itemID] = instance; 1369 if (presence != null)
1370 {
1371 ShowScriptSaveResponse(item.OwnerID,
1372 assetID, "Compile successful", true);
1309 } 1373 }
1310 }
1311 1374
1375 instance.AppDomain = appDomain;
1376 instance.LineMap = linemap;
1377 lockScriptsForWrite(true);
1378 m_Scripts[itemID] = instance;
1379 lockScriptsForWrite(false);
1380 }
1381 else
1382 {
1383 lockScriptsForRead(false);
1384 }
1312 lock (m_PrimObjects) 1385 lock (m_PrimObjects)
1313 { 1386 {
1314 if (!m_PrimObjects.ContainsKey(localID)) 1387 if (!m_PrimObjects.ContainsKey(localID))
@@ -1326,7 +1399,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1326 m_AddingAssemblies[assembly]--; 1399 m_AddingAssemblies[assembly]--;
1327 } 1400 }
1328 1401
1329 if (instance != null) 1402 if (instance!=null)
1330 instance.Init(); 1403 instance.Init();
1331 1404
1332 bool runIt; 1405 bool runIt;
@@ -1349,18 +1422,28 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1349 m_CompileDict.Remove(itemID); 1422 m_CompileDict.Remove(itemID);
1350 } 1423 }
1351 1424
1352 IScriptInstance instance = null; 1425 lockScriptsForRead(true);
1353 1426 // Do we even have it?
1354 lock (m_Scripts) 1427 if (!m_Scripts.ContainsKey(itemID))
1355 { 1428 {
1356 // Do we even have it? 1429 // Do we even have it?
1357 if (!m_Scripts.ContainsKey(itemID)) 1430 if (!m_Scripts.ContainsKey(itemID))
1358 return; 1431 return;
1359 1432
1360 instance = m_Scripts[itemID]; 1433 lockScriptsForRead(false);
1434 lockScriptsForWrite(true);
1361 m_Scripts.Remove(itemID); 1435 m_Scripts.Remove(itemID);
1436 lockScriptsForWrite(false);
1437
1438 return;
1362 } 1439 }
1440
1363 1441
1442 IScriptInstance instance=m_Scripts[itemID];
1443 lockScriptsForRead(false);
1444 lockScriptsForWrite(true);
1445 m_Scripts.Remove(itemID);
1446 lockScriptsForWrite(false);
1364 instance.ClearQueue(); 1447 instance.ClearQueue();
1365 1448
1366 instance.Stop(m_WaitForEventCompletionOnScriptStop); 1449 instance.Stop(m_WaitForEventCompletionOnScriptStop);
@@ -1397,8 +1480,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1397 1480
1398 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 1481 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
1399 if (handlerObjectRemoved != null) 1482 if (handlerObjectRemoved != null)
1400 handlerObjectRemoved(instance.ObjectID); 1483 {
1484 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
1485 handlerObjectRemoved(part.UUID);
1486 }
1401 1487
1488 CleanAssemblies();
1489
1402 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 1490 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
1403 if (handlerScriptRemoved != null) 1491 if (handlerScriptRemoved != null)
1404 handlerScriptRemoved(itemID); 1492 handlerScriptRemoved(itemID);
@@ -1659,12 +1747,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1659 private IScriptInstance GetInstance(UUID itemID) 1747 private IScriptInstance GetInstance(UUID itemID)
1660 { 1748 {
1661 IScriptInstance instance; 1749 IScriptInstance instance;
1662 lock (m_Scripts) 1750 lockScriptsForRead(true);
1751 if (!m_Scripts.ContainsKey(itemID))
1663 { 1752 {
1664 if (!m_Scripts.ContainsKey(itemID)) 1753 lockScriptsForRead(false);
1665 return null; 1754 return null;
1666 instance = m_Scripts[itemID];
1667 } 1755 }
1756 instance = m_Scripts[itemID];
1757 lockScriptsForRead(false);
1668 return instance; 1758 return instance;
1669 } 1759 }
1670 1760
@@ -1688,6 +1778,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1688 return false; 1778 return false;
1689 } 1779 }
1690 1780
1781 [DebuggerNonUserCode]
1691 public void ApiResetScript(UUID itemID) 1782 public void ApiResetScript(UUID itemID)
1692 { 1783 {
1693 IScriptInstance instance = GetInstance(itemID); 1784 IScriptInstance instance = GetInstance(itemID);
@@ -1749,6 +1840,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1749 return UUID.Zero; 1840 return UUID.Zero;
1750 } 1841 }
1751 1842
1843 [DebuggerNonUserCode]
1752 public void SetState(UUID itemID, string newState) 1844 public void SetState(UUID itemID, string newState)
1753 { 1845 {
1754 IScriptInstance instance = GetInstance(itemID); 1846 IScriptInstance instance = GetInstance(itemID);
@@ -1771,11 +1863,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1771 1863
1772 List<IScriptInstance> instances = new List<IScriptInstance>(); 1864 List<IScriptInstance> instances = new List<IScriptInstance>();
1773 1865
1774 lock (m_Scripts) 1866 lockScriptsForRead(true);
1775 { 1867 foreach (IScriptInstance instance in m_Scripts.Values)
1776 foreach (IScriptInstance instance in m_Scripts.Values)
1777 instances.Add(instance); 1868 instances.Add(instance);
1778 } 1869 lockScriptsForRead(false);
1779 1870
1780 foreach (IScriptInstance i in instances) 1871 foreach (IScriptInstance i in instances)
1781 { 1872 {