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.cs362
1 files changed, 230 insertions, 132 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index c9bbf0e..23531a9 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -30,6 +30,7 @@ using System.IO;
30using System.Threading; 30using System.Threading;
31using System.Collections; 31using System.Collections;
32using System.Collections.Generic; 32using System.Collections.Generic;
33using System.Diagnostics; //for [DebuggerNonUserCode]
33using System.Security; 34using System.Security;
34using System.Security.Policy; 35using System.Security.Policy;
35using System.Reflection; 36using System.Reflection;
@@ -108,6 +109,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
108 private Dictionary<UUID, IScriptInstance> m_Scripts = 109 private Dictionary<UUID, IScriptInstance> m_Scripts =
109 new Dictionary<UUID, IScriptInstance>(); 110 new Dictionary<UUID, IScriptInstance>();
110 111
112 private OpenMetaverse.ReaderWriterLockSlim m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
113
111 // Maps the asset ID to the assembly 114 // Maps the asset ID to the assembly
112 115
113 private Dictionary<UUID, string> m_Assemblies = 116 private Dictionary<UUID, string> m_Assemblies =
@@ -130,6 +133,71 @@ namespace OpenSim.Region.ScriptEngine.XEngine
130 IWorkItemResult m_CurrentCompile = null; 133 IWorkItemResult m_CurrentCompile = null;
131 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>(); 134 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>();
132 135
136 private void lockScriptsForRead(bool locked)
137 {
138 if (locked)
139 {
140 if (m_scriptsLock.RecursiveReadCount > 0)
141 {
142 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.");
143 m_scriptsLock.ExitReadLock();
144 }
145 if (m_scriptsLock.RecursiveWriteCount > 0)
146 {
147 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
148 m_scriptsLock.ExitWriteLock();
149 }
150
151 while (!m_scriptsLock.TryEnterReadLock(60000))
152 {
153 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.");
154 if (m_scriptsLock.IsWriteLockHeld)
155 {
156 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
157 }
158 }
159 }
160 else
161 {
162 if (m_scriptsLock.RecursiveReadCount > 0)
163 {
164 m_scriptsLock.ExitReadLock();
165 }
166 }
167 }
168 private void lockScriptsForWrite(bool locked)
169 {
170 if (locked)
171 {
172 if (m_scriptsLock.RecursiveReadCount > 0)
173 {
174 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.");
175 m_scriptsLock.ExitReadLock();
176 }
177 if (m_scriptsLock.RecursiveWriteCount > 0)
178 {
179 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
180 m_scriptsLock.ExitWriteLock();
181 }
182
183 while (!m_scriptsLock.TryEnterWriteLock(60000))
184 {
185 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.");
186 if (m_scriptsLock.IsWriteLockHeld)
187 {
188 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
189 }
190 }
191 }
192 else
193 {
194 if (m_scriptsLock.RecursiveWriteCount > 0)
195 {
196 m_scriptsLock.ExitWriteLock();
197 }
198 }
199 }
200
133 public string ScriptEngineName 201 public string ScriptEngineName
134 { 202 {
135 get { return "XEngine"; } 203 get { return "XEngine"; }
@@ -457,44 +525,37 @@ namespace OpenSim.Region.ScriptEngine.XEngine
457 { 525 {
458 if (!m_Enabled) 526 if (!m_Enabled)
459 return; 527 return;
460 528 lockScriptsForRead(true);
461 lock (m_Scripts) 529 foreach (IScriptInstance instance in m_Scripts.Values)
462 { 530 {
463 m_log.InfoFormat( 531 // Force a final state save
464 "[XEngine]: Shutting down {0} scripts in {1}", m_Scripts.Count, m_Scene.RegionInfo.RegionName); 532 //
465 533 if (m_Assemblies.ContainsKey(instance.AssetID))
466 foreach (IScriptInstance instance in m_Scripts.Values)
467 { 534 {
468 // Force a final state save 535 string assembly = m_Assemblies[instance.AssetID];
469 // 536 instance.SaveState(assembly);
470 if (m_Assemblies.ContainsKey(instance.AssetID)) 537 }
471 {
472 string assembly = m_Assemblies[instance.AssetID];
473 instance.SaveState(assembly);
474 }
475 538
476 // Clear the event queue and abort the instance thread 539 // Clear the event queue and abort the instance thread
477 // 540 //
478 instance.ClearQueue(); 541 instance.ClearQueue();
479 instance.Stop(0); 542 instance.Stop(0);
480 543
481 // Release events, timer, etc 544 // Release events, timer, etc
482 // 545 //
483 instance.DestroyScriptInstance(); 546 instance.DestroyScriptInstance();
484 547
485 // Unload scripts and app domains. 548 // Unload scripts and app domains
486 // Must be done explicitly because they have infinite 549 // Must be done explicitly because they have infinite
487 // lifetime. 550 // lifetime
488 // However, don't bother to do this if the simulator is shutting 551 //
489 // down since it takes a long time with many scripts. 552 if (!m_SimulatorShuttingDown)
490 if (!m_SimulatorShuttingDown) 553 {
554 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
555 if (m_DomainScripts[instance.AppDomain].Count == 0)
491 { 556 {
492 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 557 m_DomainScripts.Remove(instance.AppDomain);
493 if (m_DomainScripts[instance.AppDomain].Count == 0) 558 UnloadAppDomain(instance.AppDomain);
494 {
495 m_DomainScripts.Remove(instance.AppDomain);
496 UnloadAppDomain(instance.AppDomain);
497 }
498 } 559 }
499 } 560 }
500 561
@@ -503,6 +564,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
503 m_Assemblies.Clear(); 564 m_Assemblies.Clear();
504 m_DomainScripts.Clear(); 565 m_DomainScripts.Clear();
505 } 566 }
567 lockScriptsForRead(false);
568 lockScriptsForWrite(true);
569 m_Scripts.Clear();
570 lockScriptsForWrite(false);
571 m_PrimObjects.Clear();
572 m_Assemblies.Clear();
573 m_DomainScripts.Clear();
574
506 lock (m_ScriptEngines) 575 lock (m_ScriptEngines)
507 { 576 {
508 m_ScriptEngines.Remove(this); 577 m_ScriptEngines.Remove(this);
@@ -567,22 +636,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
567 636
568 List<IScriptInstance> instances = new List<IScriptInstance>(); 637 List<IScriptInstance> instances = new List<IScriptInstance>();
569 638
570 lock (m_Scripts) 639 lockScriptsForRead(true);
571 { 640 foreach (IScriptInstance instance in m_Scripts.Values)
572 foreach (IScriptInstance instance in m_Scripts.Values)
573 instances.Add(instance); 641 instances.Add(instance);
574 } 642 lockScriptsForRead(false);
575 643
576 foreach (IScriptInstance i in instances) 644 foreach (IScriptInstance i in instances)
577 { 645 {
578 string assembly = String.Empty; 646 string assembly = String.Empty;
579 647
580 lock (m_Scripts) 648
581 {
582 if (!m_Assemblies.ContainsKey(i.AssetID)) 649 if (!m_Assemblies.ContainsKey(i.AssetID))
583 continue; 650 continue;
584 assembly = m_Assemblies[i.AssetID]; 651 assembly = m_Assemblies[i.AssetID];
585 } 652
586 653
587 i.SaveState(assembly); 654 i.SaveState(assembly);
588 } 655 }
@@ -916,92 +983,95 @@ namespace OpenSim.Region.ScriptEngine.XEngine
916 } 983 }
917 984
918 ScriptInstance instance = null; 985 ScriptInstance instance = null;
919 lock (m_Scripts) 986 // Create the object record
987 lockScriptsForRead(true);
988 if ((!m_Scripts.ContainsKey(itemID)) ||
989 (m_Scripts[itemID].AssetID != assetID))
920 { 990 {
921 // Create the object record 991 lockScriptsForRead(false);
922 992
923 if ((!m_Scripts.ContainsKey(itemID)) || 993 UUID appDomain = assetID;
924 (m_Scripts[itemID].AssetID != assetID))
925 {
926 UUID appDomain = assetID;
927 994
928 if (part.ParentGroup.IsAttachment) 995 if (part.ParentGroup.IsAttachment)
929 appDomain = part.ParentGroup.RootPart.UUID; 996 appDomain = part.ParentGroup.RootPart.UUID;
930 997
931 if (!m_AppDomains.ContainsKey(appDomain)) 998 if (!m_AppDomains.ContainsKey(appDomain))
999 {
1000 try
932 { 1001 {
933 try 1002 AppDomainSetup appSetup = new AppDomainSetup();
934 { 1003 appSetup.PrivateBinPath = Path.Combine(
935 AppDomainSetup appSetup = new AppDomainSetup(); 1004 m_ScriptEnginesPath,
936 appSetup.PrivateBinPath = Path.Combine( 1005 m_Scene.RegionInfo.RegionID.ToString());
937 m_ScriptEnginesPath, 1006
938 m_Scene.RegionInfo.RegionID.ToString()); 1007 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
939 1008 Evidence evidence = new Evidence(baseEvidence);
940 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 1009
941 Evidence evidence = new Evidence(baseEvidence); 1010 AppDomain sandbox;
942 1011 if (m_AppDomainLoading)
943 AppDomain sandbox; 1012 sandbox = AppDomain.CreateDomain(
944 if (m_AppDomainLoading) 1013 m_Scene.RegionInfo.RegionID.ToString(),
945 sandbox = AppDomain.CreateDomain( 1014 evidence, appSetup);
946 m_Scene.RegionInfo.RegionID.ToString(), 1015 else
947 evidence, appSetup); 1016 sandbox = AppDomain.CurrentDomain;
948 else 1017
949 sandbox = AppDomain.CurrentDomain; 1018 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
950 1019 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
951 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); 1020 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
952 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); 1021 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
953 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet"); 1022 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
954 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet); 1023 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
955 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement); 1024 //sandbox.SetAppDomainPolicy(sandboxPolicy);
956 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup; 1025
957 //sandbox.SetAppDomainPolicy(sandboxPolicy); 1026 m_AppDomains[appDomain] = sandbox;
958 1027
959 m_AppDomains[appDomain] = sandbox; 1028 m_AppDomains[appDomain].AssemblyResolve +=
960 1029 new ResolveEventHandler(
961 m_AppDomains[appDomain].AssemblyResolve += 1030 AssemblyResolver.OnAssemblyResolve);
962 new ResolveEventHandler( 1031 m_DomainScripts[appDomain] = new List<UUID>();
963 AssemblyResolver.OnAssemblyResolve); 1032 }
964 m_DomainScripts[appDomain] = new List<UUID>(); 1033 catch (Exception e)
965 } 1034 {
966 catch (Exception e) 1035 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
1036 m_ScriptErrorMessage += "Exception creating app domain:\n";
1037 m_ScriptFailCount++;
1038 lock (m_AddingAssemblies)
967 { 1039 {
968 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); 1040 m_AddingAssemblies[assembly]--;
969 m_ScriptErrorMessage += "Exception creating app domain:\n";
970 m_ScriptFailCount++;
971 lock (m_AddingAssemblies)
972 {
973 m_AddingAssemblies[assembly]--;
974 }
975 return false;
976 } 1041 }
1042 return false;
977 } 1043 }
978 m_DomainScripts[appDomain].Add(itemID); 1044 }
979 1045 m_DomainScripts[appDomain].Add(itemID);
980 instance = new ScriptInstance(this, part, 1046
981 itemID, assetID, assembly, 1047 instance = new ScriptInstance(this, part,
982 m_AppDomains[appDomain], 1048 itemID, assetID, assembly,
983 part.ParentGroup.RootPart.Name, 1049 m_AppDomains[appDomain],
984 item.Name, startParam, postOnRez, 1050 part.ParentGroup.RootPart.Name,
985 stateSource, m_MaxScriptQueue); 1051 item.Name, startParam, postOnRez,
986 1052 stateSource, m_MaxScriptQueue);
987 m_log.DebugFormat( 1053
988 "[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", 1054 m_log.DebugFormat(
989 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, 1055 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1056 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
990 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); 1057 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
991 1058
992 if (presence != null) 1059 if (presence != null)
993 { 1060 {
994 ShowScriptSaveResponse(item.OwnerID, 1061 ShowScriptSaveResponse(item.OwnerID,
995 assetID, "Compile successful", true); 1062 assetID, "Compile successful", true);
996 }
997
998 instance.AppDomain = appDomain;
999 instance.LineMap = linemap;
1000
1001 m_Scripts[itemID] = instance;
1002 } 1063 }
1003 }
1004 1064
1065 instance.AppDomain = appDomain;
1066 instance.LineMap = linemap;
1067 lockScriptsForWrite(true);
1068 m_Scripts[itemID] = instance;
1069 lockScriptsForWrite(false);
1070 }
1071 else
1072 {
1073 lockScriptsForRead(false);
1074 }
1005 lock (m_PrimObjects) 1075 lock (m_PrimObjects)
1006 { 1076 {
1007 if (!m_PrimObjects.ContainsKey(localID)) 1077 if (!m_PrimObjects.ContainsKey(localID))
@@ -1020,9 +1090,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1020 m_AddingAssemblies[assembly]--; 1090 m_AddingAssemblies[assembly]--;
1021 } 1091 }
1022 1092
1023 if (instance != null) 1093 if (instance!=null)
1024 instance.Init(); 1094 instance.Init();
1025 1095
1026 return true; 1096 return true;
1027 } 1097 }
1028 1098
@@ -1035,20 +1105,31 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1035 m_CompileDict.Remove(itemID); 1105 m_CompileDict.Remove(itemID);
1036 } 1106 }
1037 1107
1038 IScriptInstance instance = null; 1108 lockScriptsForRead(true);
1039 1109 // Do we even have it?
1040 lock (m_Scripts) 1110 if (!m_Scripts.ContainsKey(itemID))
1041 { 1111 {
1042 // Do we even have it? 1112 // Do we even have it?
1043 if (!m_Scripts.ContainsKey(itemID)) 1113 if (!m_Scripts.ContainsKey(itemID))
1044 return; 1114 return;
1045 1115
1046 instance = m_Scripts[itemID]; 1116 lockScriptsForRead(false);
1117 lockScriptsForWrite(true);
1047 m_Scripts.Remove(itemID); 1118 m_Scripts.Remove(itemID);
1119 lockScriptsForWrite(false);
1120
1121 return;
1048 } 1122 }
1123
1049 1124
1125 IScriptInstance instance=m_Scripts[itemID];
1126 lockScriptsForRead(false);
1127 lockScriptsForWrite(true);
1128 m_Scripts.Remove(itemID);
1129 lockScriptsForWrite(false);
1050 instance.ClearQueue(); 1130 instance.ClearQueue();
1051 instance.Stop(0); 1131 instance.Stop(0);
1132
1052// bool objectRemoved = false; 1133// bool objectRemoved = false;
1053 1134
1054 lock (m_PrimObjects) 1135 lock (m_PrimObjects)
@@ -1084,11 +1165,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1084 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 1165 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
1085 if (handlerObjectRemoved != null) 1166 if (handlerObjectRemoved != null)
1086 { 1167 {
1087 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID); 1168 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
1088 handlerObjectRemoved(part.UUID); 1169 handlerObjectRemoved(part.UUID);
1089 } 1170 }
1090 1171
1091 1172 CleanAssemblies();
1173
1092 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 1174 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
1093 if (handlerScriptRemoved != null) 1175 if (handlerScriptRemoved != null)
1094 handlerScriptRemoved(itemID); 1176 handlerScriptRemoved(itemID);
@@ -1230,7 +1312,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1230 return false; 1312 return false;
1231 1313
1232 uuids = m_PrimObjects[localID]; 1314 uuids = m_PrimObjects[localID];
1233 } 1315
1234 1316
1235 foreach (UUID itemID in uuids) 1317 foreach (UUID itemID in uuids)
1236 { 1318 {
@@ -1248,6 +1330,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1248 result = true; 1330 result = true;
1249 } 1331 }
1250 } 1332 }
1333 }
1251 1334
1252 return result; 1335 return result;
1253 } 1336 }
@@ -1347,12 +1430,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1347 private IScriptInstance GetInstance(UUID itemID) 1430 private IScriptInstance GetInstance(UUID itemID)
1348 { 1431 {
1349 IScriptInstance instance; 1432 IScriptInstance instance;
1350 lock (m_Scripts) 1433 lockScriptsForRead(true);
1434 if (!m_Scripts.ContainsKey(itemID))
1351 { 1435 {
1352 if (!m_Scripts.ContainsKey(itemID)) 1436 lockScriptsForRead(false);
1353 return null; 1437 return null;
1354 instance = m_Scripts[itemID];
1355 } 1438 }
1439 instance = m_Scripts[itemID];
1440 lockScriptsForRead(false);
1356 return instance; 1441 return instance;
1357 } 1442 }
1358 1443
@@ -1376,6 +1461,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1376 return false; 1461 return false;
1377 } 1462 }
1378 1463
1464 [DebuggerNonUserCode]
1379 public void ApiResetScript(UUID itemID) 1465 public void ApiResetScript(UUID itemID)
1380 { 1466 {
1381 IScriptInstance instance = GetInstance(itemID); 1467 IScriptInstance instance = GetInstance(itemID);
@@ -1427,6 +1513,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1427 return UUID.Zero; 1513 return UUID.Zero;
1428 } 1514 }
1429 1515
1516 [DebuggerNonUserCode]
1430 public void SetState(UUID itemID, string newState) 1517 public void SetState(UUID itemID, string newState)
1431 { 1518 {
1432 IScriptInstance instance = GetInstance(itemID); 1519 IScriptInstance instance = GetInstance(itemID);
@@ -1449,11 +1536,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1449 1536
1450 List<IScriptInstance> instances = new List<IScriptInstance>(); 1537 List<IScriptInstance> instances = new List<IScriptInstance>();
1451 1538
1452 lock (m_Scripts) 1539 lockScriptsForRead(true);
1453 { 1540 foreach (IScriptInstance instance in m_Scripts.Values)
1454 foreach (IScriptInstance instance in m_Scripts.Values)
1455 instances.Add(instance); 1541 instances.Add(instance);
1456 } 1542 lockScriptsForRead(false);
1457 1543
1458 foreach (IScriptInstance i in instances) 1544 foreach (IScriptInstance i in instances)
1459 { 1545 {
@@ -1830,5 +1916,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1830 if (instance != null) 1916 if (instance != null)
1831 instance.Resume(); 1917 instance.Resume();
1832 } 1918 }
1919
1920 public bool HasScript(UUID itemID, out bool running)
1921 {
1922 running = true;
1923
1924 IScriptInstance instance = GetInstance(itemID);
1925 if (instance == null)
1926 return false;
1927
1928 running = instance.Running;
1929 return true;
1930 }
1833 } 1931 }
1834} \ No newline at end of file 1932}