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 12e1a78..65c7416 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"; }
@@ -450,44 +518,37 @@ namespace OpenSim.Region.ScriptEngine.XEngine
450 { 518 {
451 if (!m_Enabled) 519 if (!m_Enabled)
452 return; 520 return;
453 521 lockScriptsForRead(true);
454 lock (m_Scripts) 522 foreach (IScriptInstance instance in m_Scripts.Values)
455 { 523 {
456 m_log.InfoFormat( 524 // Force a final state save
457 "[XEngine]: Shutting down {0} scripts in {1}", m_Scripts.Count, m_Scene.RegionInfo.RegionName); 525 //
458 526 if (m_Assemblies.ContainsKey(instance.AssetID))
459 foreach (IScriptInstance instance in m_Scripts.Values)
460 { 527 {
461 // Force a final state save 528 string assembly = m_Assemblies[instance.AssetID];
462 // 529 instance.SaveState(assembly);
463 if (m_Assemblies.ContainsKey(instance.AssetID)) 530 }
464 {
465 string assembly = m_Assemblies[instance.AssetID];
466 instance.SaveState(assembly);
467 }
468 531
469 // Clear the event queue and abort the instance thread 532 // Clear the event queue and abort the instance thread
470 // 533 //
471 instance.ClearQueue(); 534 instance.ClearQueue();
472 instance.Stop(0); 535 instance.Stop(0);
473 536
474 // Release events, timer, etc 537 // Release events, timer, etc
475 // 538 //
476 instance.DestroyScriptInstance(); 539 instance.DestroyScriptInstance();
477 540
478 // Unload scripts and app domains. 541 // Unload scripts and app domains
479 // Must be done explicitly because they have infinite 542 // Must be done explicitly because they have infinite
480 // lifetime. 543 // lifetime
481 // However, don't bother to do this if the simulator is shutting 544 //
482 // down since it takes a long time with many scripts. 545 if (!m_SimulatorShuttingDown)
483 if (!m_SimulatorShuttingDown) 546 {
547 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
548 if (m_DomainScripts[instance.AppDomain].Count == 0)
484 { 549 {
485 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 550 m_DomainScripts.Remove(instance.AppDomain);
486 if (m_DomainScripts[instance.AppDomain].Count == 0) 551 UnloadAppDomain(instance.AppDomain);
487 {
488 m_DomainScripts.Remove(instance.AppDomain);
489 UnloadAppDomain(instance.AppDomain);
490 }
491 } 552 }
492 } 553 }
493 554
@@ -496,6 +557,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
496 m_Assemblies.Clear(); 557 m_Assemblies.Clear();
497 m_DomainScripts.Clear(); 558 m_DomainScripts.Clear();
498 } 559 }
560 lockScriptsForRead(false);
561 lockScriptsForWrite(true);
562 m_Scripts.Clear();
563 lockScriptsForWrite(false);
564 m_PrimObjects.Clear();
565 m_Assemblies.Clear();
566 m_DomainScripts.Clear();
567
499 lock (m_ScriptEngines) 568 lock (m_ScriptEngines)
500 { 569 {
501 m_ScriptEngines.Remove(this); 570 m_ScriptEngines.Remove(this);
@@ -560,22 +629,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
560 629
561 List<IScriptInstance> instances = new List<IScriptInstance>(); 630 List<IScriptInstance> instances = new List<IScriptInstance>();
562 631
563 lock (m_Scripts) 632 lockScriptsForRead(true);
564 { 633 foreach (IScriptInstance instance in m_Scripts.Values)
565 foreach (IScriptInstance instance in m_Scripts.Values)
566 instances.Add(instance); 634 instances.Add(instance);
567 } 635 lockScriptsForRead(false);
568 636
569 foreach (IScriptInstance i in instances) 637 foreach (IScriptInstance i in instances)
570 { 638 {
571 string assembly = String.Empty; 639 string assembly = String.Empty;
572 640
573 lock (m_Scripts) 641
574 {
575 if (!m_Assemblies.ContainsKey(i.AssetID)) 642 if (!m_Assemblies.ContainsKey(i.AssetID))
576 continue; 643 continue;
577 assembly = m_Assemblies[i.AssetID]; 644 assembly = m_Assemblies[i.AssetID];
578 } 645
579 646
580 i.SaveState(assembly); 647 i.SaveState(assembly);
581 } 648 }
@@ -909,92 +976,95 @@ namespace OpenSim.Region.ScriptEngine.XEngine
909 } 976 }
910 977
911 ScriptInstance instance = null; 978 ScriptInstance instance = null;
912 lock (m_Scripts) 979 // Create the object record
980 lockScriptsForRead(true);
981 if ((!m_Scripts.ContainsKey(itemID)) ||
982 (m_Scripts[itemID].AssetID != assetID))
913 { 983 {
914 // Create the object record 984 lockScriptsForRead(false);
915 985
916 if ((!m_Scripts.ContainsKey(itemID)) || 986 UUID appDomain = assetID;
917 (m_Scripts[itemID].AssetID != assetID))
918 {
919 UUID appDomain = assetID;
920 987
921 if (part.ParentGroup.IsAttachment) 988 if (part.ParentGroup.IsAttachment)
922 appDomain = part.ParentGroup.RootPart.UUID; 989 appDomain = part.ParentGroup.RootPart.UUID;
923 990
924 if (!m_AppDomains.ContainsKey(appDomain)) 991 if (!m_AppDomains.ContainsKey(appDomain))
992 {
993 try
925 { 994 {
926 try 995 AppDomainSetup appSetup = new AppDomainSetup();
927 { 996 appSetup.PrivateBinPath = Path.Combine(
928 AppDomainSetup appSetup = new AppDomainSetup(); 997 m_ScriptEnginesPath,
929 appSetup.PrivateBinPath = Path.Combine( 998 m_Scene.RegionInfo.RegionID.ToString());
930 m_ScriptEnginesPath, 999
931 m_Scene.RegionInfo.RegionID.ToString()); 1000 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
932 1001 Evidence evidence = new Evidence(baseEvidence);
933 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 1002
934 Evidence evidence = new Evidence(baseEvidence); 1003 AppDomain sandbox;
935 1004 if (m_AppDomainLoading)
936 AppDomain sandbox; 1005 sandbox = AppDomain.CreateDomain(
937 if (m_AppDomainLoading) 1006 m_Scene.RegionInfo.RegionID.ToString(),
938 sandbox = AppDomain.CreateDomain( 1007 evidence, appSetup);
939 m_Scene.RegionInfo.RegionID.ToString(), 1008 else
940 evidence, appSetup); 1009 sandbox = AppDomain.CurrentDomain;
941 else 1010
942 sandbox = AppDomain.CurrentDomain; 1011 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
943 1012 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
944 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); 1013 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
945 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); 1014 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
946 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet"); 1015 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
947 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet); 1016 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
948 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement); 1017 //sandbox.SetAppDomainPolicy(sandboxPolicy);
949 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup; 1018
950 //sandbox.SetAppDomainPolicy(sandboxPolicy); 1019 m_AppDomains[appDomain] = sandbox;
951 1020
952 m_AppDomains[appDomain] = sandbox; 1021 m_AppDomains[appDomain].AssemblyResolve +=
953 1022 new ResolveEventHandler(
954 m_AppDomains[appDomain].AssemblyResolve += 1023 AssemblyResolver.OnAssemblyResolve);
955 new ResolveEventHandler( 1024 m_DomainScripts[appDomain] = new List<UUID>();
956 AssemblyResolver.OnAssemblyResolve); 1025 }
957 m_DomainScripts[appDomain] = new List<UUID>(); 1026 catch (Exception e)
958 } 1027 {
959 catch (Exception e) 1028 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
1029 m_ScriptErrorMessage += "Exception creating app domain:\n";
1030 m_ScriptFailCount++;
1031 lock (m_AddingAssemblies)
960 { 1032 {
961 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); 1033 m_AddingAssemblies[assembly]--;
962 m_ScriptErrorMessage += "Exception creating app domain:\n";
963 m_ScriptFailCount++;
964 lock (m_AddingAssemblies)
965 {
966 m_AddingAssemblies[assembly]--;
967 }
968 return false;
969 } 1034 }
1035 return false;
970 } 1036 }
971 m_DomainScripts[appDomain].Add(itemID); 1037 }
972 1038 m_DomainScripts[appDomain].Add(itemID);
973 instance = new ScriptInstance(this, part, 1039
974 itemID, assetID, assembly, 1040 instance = new ScriptInstance(this, part,
975 m_AppDomains[appDomain], 1041 itemID, assetID, assembly,
976 part.ParentGroup.RootPart.Name, 1042 m_AppDomains[appDomain],
977 item.Name, startParam, postOnRez, 1043 part.ParentGroup.RootPart.Name,
978 stateSource, m_MaxScriptQueue); 1044 item.Name, startParam, postOnRez,
979 1045 stateSource, m_MaxScriptQueue);
980 m_log.DebugFormat( 1046
981 "[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", 1047 m_log.DebugFormat(
982 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, 1048 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1049 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
983 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); 1050 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
984 1051
985 if (presence != null) 1052 if (presence != null)
986 { 1053 {
987 ShowScriptSaveResponse(item.OwnerID, 1054 ShowScriptSaveResponse(item.OwnerID,
988 assetID, "Compile successful", true); 1055 assetID, "Compile successful", true);
989 }
990
991 instance.AppDomain = appDomain;
992 instance.LineMap = linemap;
993
994 m_Scripts[itemID] = instance;
995 } 1056 }
996 }
997 1057
1058 instance.AppDomain = appDomain;
1059 instance.LineMap = linemap;
1060 lockScriptsForWrite(true);
1061 m_Scripts[itemID] = instance;
1062 lockScriptsForWrite(false);
1063 }
1064 else
1065 {
1066 lockScriptsForRead(false);
1067 }
998 lock (m_PrimObjects) 1068 lock (m_PrimObjects)
999 { 1069 {
1000 if (!m_PrimObjects.ContainsKey(localID)) 1070 if (!m_PrimObjects.ContainsKey(localID))
@@ -1013,9 +1083,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1013 m_AddingAssemblies[assembly]--; 1083 m_AddingAssemblies[assembly]--;
1014 } 1084 }
1015 1085
1016 if (instance != null) 1086 if (instance!=null)
1017 instance.Init(); 1087 instance.Init();
1018 1088
1019 return true; 1089 return true;
1020 } 1090 }
1021 1091
@@ -1028,20 +1098,31 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1028 m_CompileDict.Remove(itemID); 1098 m_CompileDict.Remove(itemID);
1029 } 1099 }
1030 1100
1031 IScriptInstance instance = null; 1101 lockScriptsForRead(true);
1032 1102 // Do we even have it?
1033 lock (m_Scripts) 1103 if (!m_Scripts.ContainsKey(itemID))
1034 { 1104 {
1035 // Do we even have it? 1105 // Do we even have it?
1036 if (!m_Scripts.ContainsKey(itemID)) 1106 if (!m_Scripts.ContainsKey(itemID))
1037 return; 1107 return;
1038 1108
1039 instance = m_Scripts[itemID]; 1109 lockScriptsForRead(false);
1110 lockScriptsForWrite(true);
1040 m_Scripts.Remove(itemID); 1111 m_Scripts.Remove(itemID);
1112 lockScriptsForWrite(false);
1113
1114 return;
1041 } 1115 }
1116
1042 1117
1118 IScriptInstance instance=m_Scripts[itemID];
1119 lockScriptsForRead(false);
1120 lockScriptsForWrite(true);
1121 m_Scripts.Remove(itemID);
1122 lockScriptsForWrite(false);
1043 instance.ClearQueue(); 1123 instance.ClearQueue();
1044 instance.Stop(0); 1124 instance.Stop(0);
1125
1045// bool objectRemoved = false; 1126// bool objectRemoved = false;
1046 1127
1047 lock (m_PrimObjects) 1128 lock (m_PrimObjects)
@@ -1077,11 +1158,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1077 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 1158 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
1078 if (handlerObjectRemoved != null) 1159 if (handlerObjectRemoved != null)
1079 { 1160 {
1080 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID); 1161 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
1081 handlerObjectRemoved(part.UUID); 1162 handlerObjectRemoved(part.UUID);
1082 } 1163 }
1083 1164
1084 1165 CleanAssemblies();
1166
1085 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 1167 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
1086 if (handlerScriptRemoved != null) 1168 if (handlerScriptRemoved != null)
1087 handlerScriptRemoved(itemID); 1169 handlerScriptRemoved(itemID);
@@ -1223,7 +1305,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1223 return false; 1305 return false;
1224 1306
1225 uuids = m_PrimObjects[localID]; 1307 uuids = m_PrimObjects[localID];
1226 } 1308
1227 1309
1228 foreach (UUID itemID in uuids) 1310 foreach (UUID itemID in uuids)
1229 { 1311 {
@@ -1241,6 +1323,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1241 result = true; 1323 result = true;
1242 } 1324 }
1243 } 1325 }
1326 }
1244 1327
1245 return result; 1328 return result;
1246 } 1329 }
@@ -1340,12 +1423,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1340 private IScriptInstance GetInstance(UUID itemID) 1423 private IScriptInstance GetInstance(UUID itemID)
1341 { 1424 {
1342 IScriptInstance instance; 1425 IScriptInstance instance;
1343 lock (m_Scripts) 1426 lockScriptsForRead(true);
1427 if (!m_Scripts.ContainsKey(itemID))
1344 { 1428 {
1345 if (!m_Scripts.ContainsKey(itemID)) 1429 lockScriptsForRead(false);
1346 return null; 1430 return null;
1347 instance = m_Scripts[itemID];
1348 } 1431 }
1432 instance = m_Scripts[itemID];
1433 lockScriptsForRead(false);
1349 return instance; 1434 return instance;
1350 } 1435 }
1351 1436
@@ -1369,6 +1454,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1369 return false; 1454 return false;
1370 } 1455 }
1371 1456
1457 [DebuggerNonUserCode]
1372 public void ApiResetScript(UUID itemID) 1458 public void ApiResetScript(UUID itemID)
1373 { 1459 {
1374 IScriptInstance instance = GetInstance(itemID); 1460 IScriptInstance instance = GetInstance(itemID);
@@ -1420,6 +1506,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1420 return UUID.Zero; 1506 return UUID.Zero;
1421 } 1507 }
1422 1508
1509 [DebuggerNonUserCode]
1423 public void SetState(UUID itemID, string newState) 1510 public void SetState(UUID itemID, string newState)
1424 { 1511 {
1425 IScriptInstance instance = GetInstance(itemID); 1512 IScriptInstance instance = GetInstance(itemID);
@@ -1442,11 +1529,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1442 1529
1443 List<IScriptInstance> instances = new List<IScriptInstance>(); 1530 List<IScriptInstance> instances = new List<IScriptInstance>();
1444 1531
1445 lock (m_Scripts) 1532 lockScriptsForRead(true);
1446 { 1533 foreach (IScriptInstance instance in m_Scripts.Values)
1447 foreach (IScriptInstance instance in m_Scripts.Values)
1448 instances.Add(instance); 1534 instances.Add(instance);
1449 } 1535 lockScriptsForRead(false);
1450 1536
1451 foreach (IScriptInstance i in instances) 1537 foreach (IScriptInstance i in instances)
1452 { 1538 {
@@ -1823,5 +1909,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1823 if (instance != null) 1909 if (instance != null)
1824 instance.Resume(); 1910 instance.Resume();
1825 } 1911 }
1912
1913 public bool HasScript(UUID itemID, out bool running)
1914 {
1915 running = true;
1916
1917 IScriptInstance instance = GetInstance(itemID);
1918 if (instance == null)
1919 return false;
1920
1921 running = instance.Running;
1922 return true;
1923 }
1826 } 1924 }
1827} \ No newline at end of file 1925}