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.cs363
1 files changed, 224 insertions, 139 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index d483219..6e04e79 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;
@@ -149,6 +150,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
149 private Dictionary<UUID, IScriptInstance> m_Scripts = 150 private Dictionary<UUID, IScriptInstance> m_Scripts =
150 new Dictionary<UUID, IScriptInstance>(); 151 new Dictionary<UUID, IScriptInstance>();
151 152
153 private OpenMetaverse.ReaderWriterLockSlim m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
154
152 // Maps the asset ID to the assembly 155 // Maps the asset ID to the assembly
153 156
154 private Dictionary<UUID, string> m_Assemblies = 157 private Dictionary<UUID, string> m_Assemblies =
@@ -171,6 +174,71 @@ namespace OpenSim.Region.ScriptEngine.XEngine
171 IWorkItemResult m_CurrentCompile = null; 174 IWorkItemResult m_CurrentCompile = null;
172 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>(); 175 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>();
173 176
177 private void lockScriptsForRead(bool locked)
178 {
179 if (locked)
180 {
181 if (m_scriptsLock.RecursiveReadCount > 0)
182 {
183 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.");
184 m_scriptsLock.ExitReadLock();
185 }
186 if (m_scriptsLock.RecursiveWriteCount > 0)
187 {
188 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
189 m_scriptsLock.ExitWriteLock();
190 }
191
192 while (!m_scriptsLock.TryEnterReadLock(60000))
193 {
194 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.");
195 if (m_scriptsLock.IsWriteLockHeld)
196 {
197 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
198 }
199 }
200 }
201 else
202 {
203 if (m_scriptsLock.RecursiveReadCount > 0)
204 {
205 m_scriptsLock.ExitReadLock();
206 }
207 }
208 }
209 private void lockScriptsForWrite(bool locked)
210 {
211 if (locked)
212 {
213 if (m_scriptsLock.RecursiveReadCount > 0)
214 {
215 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.");
216 m_scriptsLock.ExitReadLock();
217 }
218 if (m_scriptsLock.RecursiveWriteCount > 0)
219 {
220 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
221 m_scriptsLock.ExitWriteLock();
222 }
223
224 while (!m_scriptsLock.TryEnterWriteLock(60000))
225 {
226 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.");
227 if (m_scriptsLock.IsWriteLockHeld)
228 {
229 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
230 }
231 }
232 }
233 else
234 {
235 if (m_scriptsLock.RecursiveWriteCount > 0)
236 {
237 m_scriptsLock.ExitWriteLock();
238 }
239 }
240 }
241
174 private ScriptEngineConsoleCommands m_consoleCommands; 242 private ScriptEngineConsoleCommands m_consoleCommands;
175 243
176 public string ScriptEngineName 244 public string ScriptEngineName
@@ -701,64 +769,69 @@ namespace OpenSim.Region.ScriptEngine.XEngine
701 { 769 {
702 if (!m_Enabled) 770 if (!m_Enabled)
703 return; 771 return;
772 lockScriptsForRead(true);
704 773
705 lock (m_Scripts) 774 List<IScriptInstance> instancesToDel = new List<IScriptInstance>(m_Scripts.Values);
706 {
707 m_log.InfoFormat(
708 "[XEngine]: Shutting down {0} scripts in {1}", m_Scripts.Count, m_Scene.RegionInfo.RegionName);
709 775
710 foreach (IScriptInstance instance in m_Scripts.Values) 776// foreach (IScriptInstance instance in m_Scripts.Values)
777 foreach (IScriptInstance instance in instancesToDel)
778 {
779 // Force a final state save
780 //
781 if (m_Assemblies.ContainsKey(instance.AssetID))
711 { 782 {
712 // Force a final state save 783 string assembly = m_Assemblies[instance.AssetID];
713 //
714 if (m_Assemblies.ContainsKey(instance.AssetID))
715 {
716 string assembly = m_Assemblies[instance.AssetID];
717 784
718 try 785 try
719 { 786 {
720 instance.SaveState(assembly); 787 instance.SaveState(assembly);
721 }
722 catch (Exception e)
723 {
724 m_log.Error(
725 string.Format(
726 "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ",
727 instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name)
728 , e);
729 }
730 } 788 }
789 catch (Exception e)
790 {
791 m_log.Error(
792 string.Format(
793 "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ",
794 instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name)
795 , e);
796 }
797 }
731 798
732 // Clear the event queue and abort the instance thread 799 // Clear the event queue and abort the instance thread
733 // 800 //
734 instance.ClearQueue(); 801 instance.ClearQueue();
735 instance.Stop(0); 802 instance.Stop(0);
736 803
737 // Release events, timer, etc 804 // Release events, timer, etc
738 // 805 //
739 instance.DestroyScriptInstance(); 806 instance.DestroyScriptInstance();
740 807
741 // Unload scripts and app domains. 808 // Unload scripts and app domains
742 // Must be done explicitly because they have infinite 809 // Must be done explicitly because they have infinite
743 // lifetime. 810 // lifetime
744 // However, don't bother to do this if the simulator is shutting 811 //
745 // down since it takes a long time with many scripts. 812// if (!m_SimulatorShuttingDown)
746 if (!m_SimulatorShuttingDown) 813 {
814 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
815 if (m_DomainScripts[instance.AppDomain].Count == 0)
747 { 816 {
748 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 817 m_DomainScripts.Remove(instance.AppDomain);
749 if (m_DomainScripts[instance.AppDomain].Count == 0) 818 UnloadAppDomain(instance.AppDomain);
750 {
751 m_DomainScripts.Remove(instance.AppDomain);
752 UnloadAppDomain(instance.AppDomain);
753 }
754 } 819 }
755 } 820 }
756 821
757 m_Scripts.Clear(); 822// m_Scripts.Clear();
758 m_PrimObjects.Clear(); 823// m_PrimObjects.Clear();
759 m_Assemblies.Clear(); 824// m_Assemblies.Clear();
760 m_DomainScripts.Clear(); 825// m_DomainScripts.Clear();
761 } 826 }
827 lockScriptsForRead(false);
828 lockScriptsForWrite(true);
829 m_Scripts.Clear();
830 lockScriptsForWrite(false);
831 m_PrimObjects.Clear();
832 m_Assemblies.Clear();
833 m_DomainScripts.Clear();
834
762 lock (m_ScriptEngines) 835 lock (m_ScriptEngines)
763 { 836 {
764 m_ScriptEngines.Remove(this); 837 m_ScriptEngines.Remove(this);
@@ -827,22 +900,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
827 900
828 List<IScriptInstance> instances = new List<IScriptInstance>(); 901 List<IScriptInstance> instances = new List<IScriptInstance>();
829 902
830 lock (m_Scripts) 903 lockScriptsForRead(true);
831 { 904 foreach (IScriptInstance instance in m_Scripts.Values)
832 foreach (IScriptInstance instance in m_Scripts.Values)
833 instances.Add(instance); 905 instances.Add(instance);
834 } 906 lockScriptsForRead(false);
835 907
836 foreach (IScriptInstance i in instances) 908 foreach (IScriptInstance i in instances)
837 { 909 {
838 string assembly = String.Empty; 910 string assembly = String.Empty;
839 911
840 lock (m_Scripts) 912
841 {
842 if (!m_Assemblies.ContainsKey(i.AssetID)) 913 if (!m_Assemblies.ContainsKey(i.AssetID))
843 continue; 914 continue;
844 assembly = m_Assemblies[i.AssetID]; 915 assembly = m_Assemblies[i.AssetID];
845 } 916
846 917
847 try 918 try
848 { 919 {
@@ -1246,97 +1317,93 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1246 } 1317 }
1247 1318
1248 ScriptInstance instance = null; 1319 ScriptInstance instance = null;
1249 lock (m_Scripts) 1320 // Create the object record
1321 lockScriptsForRead(true);
1322 if ((!m_Scripts.ContainsKey(itemID)) ||
1323 (m_Scripts[itemID].AssetID != assetID))
1250 { 1324 {
1251 // Create the object record 1325 lockScriptsForRead(false);
1252 if ((!m_Scripts.ContainsKey(itemID)) ||
1253 (m_Scripts[itemID].AssetID != assetID))
1254 {
1255 UUID appDomain = assetID;
1256 1326
1257 if (part.ParentGroup.IsAttachment) 1327 UUID appDomain = assetID;
1258 appDomain = part.ParentGroup.RootPart.UUID;
1259 1328
1260 if (!m_AppDomains.ContainsKey(appDomain)) 1329 if (part.ParentGroup.IsAttachment)
1261 { 1330 appDomain = part.ParentGroup.RootPart.UUID;
1262 try
1263 {
1264 AppDomainSetup appSetup = new AppDomainSetup();
1265 appSetup.PrivateBinPath = Path.Combine(
1266 m_ScriptEnginesPath,
1267 m_Scene.RegionInfo.RegionID.ToString());
1268 1331
1269 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 1332 if (!m_AppDomains.ContainsKey(appDomain))
1270 Evidence evidence = new Evidence(baseEvidence); 1333 {
1334 try
1335 {
1336 AppDomainSetup appSetup = new AppDomainSetup();
1337 appSetup.PrivateBinPath = Path.Combine(
1338 m_ScriptEnginesPath,
1339 m_Scene.RegionInfo.RegionID.ToString());
1271 1340
1272 AppDomain sandbox; 1341 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
1273 if (m_AppDomainLoading) 1342 Evidence evidence = new Evidence(baseEvidence);
1274 {
1275 sandbox = AppDomain.CreateDomain(
1276 m_Scene.RegionInfo.RegionID.ToString(),
1277 evidence, appSetup);
1278 sandbox.AssemblyResolve +=
1279 new ResolveEventHandler(
1280 AssemblyResolver.OnAssemblyResolve);
1281 }
1282 else
1283 {
1284 sandbox = AppDomain.CurrentDomain;
1285 }
1286
1287 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1288 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1289 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1290 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1291 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1292 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1293 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1294
1295 m_AppDomains[appDomain] = sandbox;
1296 1343
1297 m_DomainScripts[appDomain] = new List<UUID>(); 1344 AppDomain sandbox;
1345 if (m_AppDomainLoading)
1346 {
1347 sandbox = AppDomain.CreateDomain(
1348 m_Scene.RegionInfo.RegionID.ToString(),
1349 evidence, appSetup);
1350 m_AppDomains[appDomain].AssemblyResolve +=
1351 new ResolveEventHandler(
1352 AssemblyResolver.OnAssemblyResolve);
1298 } 1353 }
1299 catch (Exception e) 1354 else
1300 { 1355 {
1301 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); 1356 sandbox = AppDomain.CurrentDomain;
1302 m_ScriptErrorMessage += "Exception creating app domain:\n";
1303 m_ScriptFailCount++;
1304 lock (m_AddingAssemblies)
1305 {
1306 m_AddingAssemblies[assembly]--;
1307 }
1308 return false;
1309 } 1357 }
1310 }
1311 m_DomainScripts[appDomain].Add(itemID);
1312
1313 instance = new ScriptInstance(this, part,
1314 item,
1315 startParam, postOnRez,
1316 m_MaxScriptQueue);
1317 1358
1318 if (!instance.Load(m_AppDomains[appDomain], assembly, stateSource)) 1359 if (!instance.Load(m_AppDomains[appDomain], assembly, stateSource))
1319 return false; 1360 return false;
1320 1361
1321// if (DebugLevel >= 1) 1362 m_AppDomains[appDomain] = sandbox;
1322// m_log.DebugFormat(
1323// "[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}",
1324// part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
1325// part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1326 1363
1327 if (presence != null) 1364 m_DomainScripts[appDomain] = new List<UUID>();
1365 }
1366 catch (Exception e)
1328 { 1367 {
1329 ShowScriptSaveResponse(item.OwnerID, 1368 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
1330 assetID, "Compile successful", true); 1369 m_ScriptErrorMessage += "Exception creating app domain:\n";
1370 m_ScriptFailCount++;
1371 lock (m_AddingAssemblies)
1372 {
1373 m_AddingAssemblies[assembly]--;
1374 }
1375 return false;
1331 } 1376 }
1377 }
1378 m_DomainScripts[appDomain].Add(itemID);
1379
1380 instance = new ScriptInstance(this, part,
1381 item,
1382 startParam, postOnRez,
1383 m_MaxScriptQueue);
1332 1384
1333 instance.AppDomain = appDomain; 1385 instance.Load(m_AppDomains[appDomain], assembly, stateSource);
1334 instance.LineMap = linemap; 1386// m_log.DebugFormat(
1387// "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1388// part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
1389// part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1335 1390
1336 m_Scripts[itemID] = instance; 1391 if (presence != null)
1392 {
1393 ShowScriptSaveResponse(item.OwnerID,
1394 assetID, "Compile successful", true);
1337 } 1395 }
1338 }
1339 1396
1397 instance.AppDomain = appDomain;
1398 instance.LineMap = linemap;
1399 lockScriptsForWrite(true);
1400 m_Scripts[itemID] = instance;
1401 lockScriptsForWrite(false);
1402 }
1403 else
1404 {
1405 lockScriptsForRead(false);
1406 }
1340 lock (m_PrimObjects) 1407 lock (m_PrimObjects)
1341 { 1408 {
1342 if (!m_PrimObjects.ContainsKey(localID)) 1409 if (!m_PrimObjects.ContainsKey(localID))
@@ -1354,7 +1421,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1354 m_AddingAssemblies[assembly]--; 1421 m_AddingAssemblies[assembly]--;
1355 } 1422 }
1356 1423
1357 if (instance != null) 1424 if (instance!=null)
1358 instance.Init(); 1425 instance.Init();
1359 1426
1360 bool runIt; 1427 bool runIt;
@@ -1377,18 +1444,28 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1377 m_CompileDict.Remove(itemID); 1444 m_CompileDict.Remove(itemID);
1378 } 1445 }
1379 1446
1380 IScriptInstance instance = null; 1447 lockScriptsForRead(true);
1381 1448 // Do we even have it?
1382 lock (m_Scripts) 1449 if (!m_Scripts.ContainsKey(itemID))
1383 { 1450 {
1384 // Do we even have it? 1451 // Do we even have it?
1385 if (!m_Scripts.ContainsKey(itemID)) 1452 if (!m_Scripts.ContainsKey(itemID))
1386 return; 1453 return;
1387 1454
1388 instance = m_Scripts[itemID]; 1455 lockScriptsForRead(false);
1456 lockScriptsForWrite(true);
1389 m_Scripts.Remove(itemID); 1457 m_Scripts.Remove(itemID);
1458 lockScriptsForWrite(false);
1459
1460 return;
1390 } 1461 }
1462
1391 1463
1464 IScriptInstance instance=m_Scripts[itemID];
1465 lockScriptsForRead(false);
1466 lockScriptsForWrite(true);
1467 m_Scripts.Remove(itemID);
1468 lockScriptsForWrite(false);
1392 instance.ClearQueue(); 1469 instance.ClearQueue();
1393 1470
1394 instance.Stop(m_WaitForEventCompletionOnScriptStop); 1471 instance.Stop(m_WaitForEventCompletionOnScriptStop);
@@ -1425,8 +1502,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1425 1502
1426 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 1503 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
1427 if (handlerObjectRemoved != null) 1504 if (handlerObjectRemoved != null)
1428 handlerObjectRemoved(instance.ObjectID); 1505 {
1506 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
1507 handlerObjectRemoved(part.UUID);
1508 }
1429 1509
1510 CleanAssemblies();
1511
1430 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 1512 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
1431 if (handlerScriptRemoved != null) 1513 if (handlerScriptRemoved != null)
1432 handlerScriptRemoved(itemID); 1514 handlerScriptRemoved(itemID);
@@ -1687,12 +1769,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1687 private IScriptInstance GetInstance(UUID itemID) 1769 private IScriptInstance GetInstance(UUID itemID)
1688 { 1770 {
1689 IScriptInstance instance; 1771 IScriptInstance instance;
1690 lock (m_Scripts) 1772 lockScriptsForRead(true);
1773 if (!m_Scripts.ContainsKey(itemID))
1691 { 1774 {
1692 if (!m_Scripts.ContainsKey(itemID)) 1775 lockScriptsForRead(false);
1693 return null; 1776 return null;
1694 instance = m_Scripts[itemID];
1695 } 1777 }
1778 instance = m_Scripts[itemID];
1779 lockScriptsForRead(false);
1696 return instance; 1780 return instance;
1697 } 1781 }
1698 1782
@@ -1716,6 +1800,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1716 return false; 1800 return false;
1717 } 1801 }
1718 1802
1803 [DebuggerNonUserCode]
1719 public void ApiResetScript(UUID itemID) 1804 public void ApiResetScript(UUID itemID)
1720 { 1805 {
1721 IScriptInstance instance = GetInstance(itemID); 1806 IScriptInstance instance = GetInstance(itemID);
@@ -1777,6 +1862,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1777 return UUID.Zero; 1862 return UUID.Zero;
1778 } 1863 }
1779 1864
1865 [DebuggerNonUserCode]
1780 public void SetState(UUID itemID, string newState) 1866 public void SetState(UUID itemID, string newState)
1781 { 1867 {
1782 IScriptInstance instance = GetInstance(itemID); 1868 IScriptInstance instance = GetInstance(itemID);
@@ -1799,11 +1885,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1799 1885
1800 List<IScriptInstance> instances = new List<IScriptInstance>(); 1886 List<IScriptInstance> instances = new List<IScriptInstance>();
1801 1887
1802 lock (m_Scripts) 1888 lockScriptsForRead(true);
1803 { 1889 foreach (IScriptInstance instance in m_Scripts.Values)
1804 foreach (IScriptInstance instance in m_Scripts.Values)
1805 instances.Add(instance); 1890 instances.Add(instance);
1806 } 1891 lockScriptsForRead(false);
1807 1892
1808 foreach (IScriptInstance i in instances) 1893 foreach (IScriptInstance i in instances)
1809 { 1894 {