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.cs359
1 files changed, 227 insertions, 132 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 240e36f..3ebeb75 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;
@@ -103,6 +104,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
103 private Dictionary<UUID, IScriptInstance> m_Scripts = 104 private Dictionary<UUID, IScriptInstance> m_Scripts =
104 new Dictionary<UUID, IScriptInstance>(); 105 new Dictionary<UUID, IScriptInstance>();
105 106
107 private OpenMetaverse.ReaderWriterLockSlim m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
108
106 // Maps the asset ID to the assembly 109 // Maps the asset ID to the assembly
107 110
108 private Dictionary<UUID, string> m_Assemblies = 111 private Dictionary<UUID, string> m_Assemblies =
@@ -125,6 +128,71 @@ namespace OpenSim.Region.ScriptEngine.XEngine
125 IWorkItemResult m_CurrentCompile = null; 128 IWorkItemResult m_CurrentCompile = null;
126 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>(); 129 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>();
127 130
131 private void lockScriptsForRead(bool locked)
132 {
133 if (locked)
134 {
135 if (m_scriptsLock.RecursiveReadCount > 0)
136 {
137 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.");
138 m_scriptsLock.ExitReadLock();
139 }
140 if (m_scriptsLock.RecursiveWriteCount > 0)
141 {
142 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
143 m_scriptsLock.ExitWriteLock();
144 }
145
146 while (!m_scriptsLock.TryEnterReadLock(60000))
147 {
148 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.");
149 if (m_scriptsLock.IsWriteLockHeld)
150 {
151 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
152 }
153 }
154 }
155 else
156 {
157 if (m_scriptsLock.RecursiveReadCount > 0)
158 {
159 m_scriptsLock.ExitReadLock();
160 }
161 }
162 }
163 private void lockScriptsForWrite(bool locked)
164 {
165 if (locked)
166 {
167 if (m_scriptsLock.RecursiveReadCount > 0)
168 {
169 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.");
170 m_scriptsLock.ExitReadLock();
171 }
172 if (m_scriptsLock.RecursiveWriteCount > 0)
173 {
174 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
175 m_scriptsLock.ExitWriteLock();
176 }
177
178 while (!m_scriptsLock.TryEnterWriteLock(60000))
179 {
180 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.");
181 if (m_scriptsLock.IsWriteLockHeld)
182 {
183 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
184 }
185 }
186 }
187 else
188 {
189 if (m_scriptsLock.RecursiveWriteCount > 0)
190 {
191 m_scriptsLock.ExitWriteLock();
192 }
193 }
194 }
195
128 public string ScriptEngineName 196 public string ScriptEngineName
129 { 197 {
130 get { return "XEngine"; } 198 get { return "XEngine"; }
@@ -442,47 +510,45 @@ namespace OpenSim.Region.ScriptEngine.XEngine
442 { 510 {
443 if (!m_Enabled) 511 if (!m_Enabled)
444 return; 512 return;
445 513 lockScriptsForRead(true);
446 lock (m_Scripts) 514 foreach (IScriptInstance instance in m_Scripts.Values)
447 { 515 {
448 m_log.InfoFormat( 516 // Force a final state save
449 "[XEngine]: Shutting down {0} scripts in {1}", m_Scripts.Count, m_Scene.RegionInfo.RegionName); 517 //
450 518 if (m_Assemblies.ContainsKey(instance.AssetID))
451 foreach (IScriptInstance instance in m_Scripts.Values)
452 { 519 {
453 // Force a final state save 520 string assembly = m_Assemblies[instance.AssetID];
454 // 521 instance.SaveState(assembly);
455 if (m_Assemblies.ContainsKey(instance.AssetID)) 522 }
456 {
457 string assembly = m_Assemblies[instance.AssetID];
458 instance.SaveState(assembly);
459 }
460 523
461 // Clear the event queue and abort the instance thread 524 // Clear the event queue and abort the instance thread
462 // 525 //
463 instance.ClearQueue(); 526 instance.ClearQueue();
464 instance.Stop(0); 527 instance.Stop(0);
465 528
466 // Release events, timer, etc 529 // Release events, timer, etc
467 // 530 //
468 instance.DestroyScriptInstance(); 531 instance.DestroyScriptInstance();
469 532
470 // Unload scripts and app domains 533 // Unload scripts and app domains
471 // Must be done explicitly because they have infinite 534 // Must be done explicitly because they have infinite
472 // lifetime 535 // lifetime
473 // 536 //
474 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 537 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
475 if (m_DomainScripts[instance.AppDomain].Count == 0) 538 if (m_DomainScripts[instance.AppDomain].Count == 0)
476 { 539 {
477 m_DomainScripts.Remove(instance.AppDomain); 540 m_DomainScripts.Remove(instance.AppDomain);
478 UnloadAppDomain(instance.AppDomain); 541 UnloadAppDomain(instance.AppDomain);
479 }
480 } 542 }
481 m_Scripts.Clear();
482 m_PrimObjects.Clear();
483 m_Assemblies.Clear();
484 m_DomainScripts.Clear();
485 } 543 }
544 lockScriptsForRead(false);
545 lockScriptsForWrite(true);
546 m_Scripts.Clear();
547 lockScriptsForWrite(false);
548 m_PrimObjects.Clear();
549 m_Assemblies.Clear();
550 m_DomainScripts.Clear();
551
486 lock (m_ScriptEngines) 552 lock (m_ScriptEngines)
487 { 553 {
488 m_ScriptEngines.Remove(this); 554 m_ScriptEngines.Remove(this);
@@ -547,22 +613,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
547 613
548 List<IScriptInstance> instances = new List<IScriptInstance>(); 614 List<IScriptInstance> instances = new List<IScriptInstance>();
549 615
550 lock (m_Scripts) 616 lockScriptsForRead(true);
551 { 617 foreach (IScriptInstance instance in m_Scripts.Values)
552 foreach (IScriptInstance instance in m_Scripts.Values)
553 instances.Add(instance); 618 instances.Add(instance);
554 } 619 lockScriptsForRead(false);
555 620
556 foreach (IScriptInstance i in instances) 621 foreach (IScriptInstance i in instances)
557 { 622 {
558 string assembly = String.Empty; 623 string assembly = String.Empty;
559 624
560 lock (m_Scripts) 625
561 {
562 if (!m_Assemblies.ContainsKey(i.AssetID)) 626 if (!m_Assemblies.ContainsKey(i.AssetID))
563 continue; 627 continue;
564 assembly = m_Assemblies[i.AssetID]; 628 assembly = m_Assemblies[i.AssetID];
565 } 629
566 630
567 i.SaveState(assembly); 631 i.SaveState(assembly);
568 } 632 }
@@ -896,92 +960,95 @@ namespace OpenSim.Region.ScriptEngine.XEngine
896 } 960 }
897 961
898 ScriptInstance instance = null; 962 ScriptInstance instance = null;
899 lock (m_Scripts) 963 // Create the object record
964 lockScriptsForRead(true);
965 if ((!m_Scripts.ContainsKey(itemID)) ||
966 (m_Scripts[itemID].AssetID != assetID))
900 { 967 {
901 // Create the object record 968 lockScriptsForRead(false);
902 969
903 if ((!m_Scripts.ContainsKey(itemID)) || 970 UUID appDomain = assetID;
904 (m_Scripts[itemID].AssetID != assetID))
905 {
906 UUID appDomain = assetID;
907 971
908 if (part.ParentGroup.IsAttachment) 972 if (part.ParentGroup.IsAttachment)
909 appDomain = part.ParentGroup.RootPart.UUID; 973 appDomain = part.ParentGroup.RootPart.UUID;
910 974
911 if (!m_AppDomains.ContainsKey(appDomain)) 975 if (!m_AppDomains.ContainsKey(appDomain))
976 {
977 try
912 { 978 {
913 try 979 AppDomainSetup appSetup = new AppDomainSetup();
914 { 980 appSetup.PrivateBinPath = Path.Combine(
915 AppDomainSetup appSetup = new AppDomainSetup(); 981 m_ScriptEnginesPath,
916 appSetup.PrivateBinPath = Path.Combine( 982 m_Scene.RegionInfo.RegionID.ToString());
917 m_ScriptEnginesPath, 983
918 m_Scene.RegionInfo.RegionID.ToString()); 984 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
919 985 Evidence evidence = new Evidence(baseEvidence);
920 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 986
921 Evidence evidence = new Evidence(baseEvidence); 987 AppDomain sandbox;
922 988 if (m_AppDomainLoading)
923 AppDomain sandbox; 989 sandbox = AppDomain.CreateDomain(
924 if (m_AppDomainLoading) 990 m_Scene.RegionInfo.RegionID.ToString(),
925 sandbox = AppDomain.CreateDomain( 991 evidence, appSetup);
926 m_Scene.RegionInfo.RegionID.ToString(), 992 else
927 evidence, appSetup); 993 sandbox = AppDomain.CurrentDomain;
928 else 994
929 sandbox = AppDomain.CurrentDomain; 995 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
930 996 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
931 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); 997 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
932 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); 998 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
933 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet"); 999 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
934 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet); 1000 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
935 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement); 1001 //sandbox.SetAppDomainPolicy(sandboxPolicy);
936 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup; 1002
937 //sandbox.SetAppDomainPolicy(sandboxPolicy); 1003 m_AppDomains[appDomain] = sandbox;
938 1004
939 m_AppDomains[appDomain] = sandbox; 1005 m_AppDomains[appDomain].AssemblyResolve +=
940 1006 new ResolveEventHandler(
941 m_AppDomains[appDomain].AssemblyResolve += 1007 AssemblyResolver.OnAssemblyResolve);
942 new ResolveEventHandler( 1008 m_DomainScripts[appDomain] = new List<UUID>();
943 AssemblyResolver.OnAssemblyResolve); 1009 }
944 m_DomainScripts[appDomain] = new List<UUID>(); 1010 catch (Exception e)
945 } 1011 {
946 catch (Exception e) 1012 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
1013 m_ScriptErrorMessage += "Exception creating app domain:\n";
1014 m_ScriptFailCount++;
1015 lock (m_AddingAssemblies)
947 { 1016 {
948 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); 1017 m_AddingAssemblies[assembly]--;
949 m_ScriptErrorMessage += "Exception creating app domain:\n";
950 m_ScriptFailCount++;
951 lock (m_AddingAssemblies)
952 {
953 m_AddingAssemblies[assembly]--;
954 }
955 return false;
956 } 1018 }
1019 return false;
957 } 1020 }
958 m_DomainScripts[appDomain].Add(itemID); 1021 }
959 1022 m_DomainScripts[appDomain].Add(itemID);
960 instance = new ScriptInstance(this, part, 1023
961 itemID, assetID, assembly, 1024 instance = new ScriptInstance(this, part,
962 m_AppDomains[appDomain], 1025 itemID, assetID, assembly,
963 part.ParentGroup.RootPart.Name, 1026 m_AppDomains[appDomain],
964 item.Name, startParam, postOnRez, 1027 part.ParentGroup.RootPart.Name,
965 stateSource, m_MaxScriptQueue); 1028 item.Name, startParam, postOnRez,
966 1029 stateSource, m_MaxScriptQueue);
967 m_log.DebugFormat( 1030
968 "[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", 1031 m_log.DebugFormat(
969 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, 1032 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1033 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
970 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); 1034 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
971 1035
972 if (presence != null) 1036 if (presence != null)
973 { 1037 {
974 ShowScriptSaveResponse(item.OwnerID, 1038 ShowScriptSaveResponse(item.OwnerID,
975 assetID, "Compile successful", true); 1039 assetID, "Compile successful", true);
976 }
977
978 instance.AppDomain = appDomain;
979 instance.LineMap = linemap;
980
981 m_Scripts[itemID] = instance;
982 } 1040 }
983 }
984 1041
1042 instance.AppDomain = appDomain;
1043 instance.LineMap = linemap;
1044 lockScriptsForWrite(true);
1045 m_Scripts[itemID] = instance;
1046 lockScriptsForWrite(false);
1047 }
1048 else
1049 {
1050 lockScriptsForRead(false);
1051 }
985 lock (m_PrimObjects) 1052 lock (m_PrimObjects)
986 { 1053 {
987 if (!m_PrimObjects.ContainsKey(localID)) 1054 if (!m_PrimObjects.ContainsKey(localID))
@@ -1000,9 +1067,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1000 m_AddingAssemblies[assembly]--; 1067 m_AddingAssemblies[assembly]--;
1001 } 1068 }
1002 1069
1003 if (instance != null) 1070 if (instance!=null)
1004 instance.Init(); 1071 instance.Init();
1005 1072
1006 return true; 1073 return true;
1007 } 1074 }
1008 1075
@@ -1015,20 +1082,31 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1015 m_CompileDict.Remove(itemID); 1082 m_CompileDict.Remove(itemID);
1016 } 1083 }
1017 1084
1018 IScriptInstance instance = null; 1085 lockScriptsForRead(true);
1019 1086 // Do we even have it?
1020 lock (m_Scripts) 1087 if (!m_Scripts.ContainsKey(itemID))
1021 { 1088 {
1022 // Do we even have it? 1089 // Do we even have it?
1023 if (!m_Scripts.ContainsKey(itemID)) 1090 if (!m_Scripts.ContainsKey(itemID))
1024 return; 1091 return;
1025 1092
1026 instance = m_Scripts[itemID]; 1093 lockScriptsForRead(false);
1094 lockScriptsForWrite(true);
1027 m_Scripts.Remove(itemID); 1095 m_Scripts.Remove(itemID);
1096 lockScriptsForWrite(false);
1097
1098 return;
1028 } 1099 }
1100
1029 1101
1102 IScriptInstance instance=m_Scripts[itemID];
1103 lockScriptsForRead(false);
1104 lockScriptsForWrite(true);
1105 m_Scripts.Remove(itemID);
1106 lockScriptsForWrite(false);
1030 instance.ClearQueue(); 1107 instance.ClearQueue();
1031 instance.Stop(0); 1108 instance.Stop(0);
1109
1032// bool objectRemoved = false; 1110// bool objectRemoved = false;
1033 1111
1034 lock (m_PrimObjects) 1112 lock (m_PrimObjects)
@@ -1064,11 +1142,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1064 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 1142 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
1065 if (handlerObjectRemoved != null) 1143 if (handlerObjectRemoved != null)
1066 { 1144 {
1067 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID); 1145 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
1068 handlerObjectRemoved(part.UUID); 1146 handlerObjectRemoved(part.UUID);
1069 } 1147 }
1070 1148
1071 1149 CleanAssemblies();
1150
1072 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 1151 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
1073 if (handlerScriptRemoved != null) 1152 if (handlerScriptRemoved != null)
1074 handlerScriptRemoved(itemID); 1153 handlerScriptRemoved(itemID);
@@ -1210,7 +1289,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1210 return false; 1289 return false;
1211 1290
1212 uuids = m_PrimObjects[localID]; 1291 uuids = m_PrimObjects[localID];
1213 } 1292
1214 1293
1215 foreach (UUID itemID in uuids) 1294 foreach (UUID itemID in uuids)
1216 { 1295 {
@@ -1228,6 +1307,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1228 result = true; 1307 result = true;
1229 } 1308 }
1230 } 1309 }
1310 }
1231 1311
1232 return result; 1312 return result;
1233 } 1313 }
@@ -1327,12 +1407,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1327 private IScriptInstance GetInstance(UUID itemID) 1407 private IScriptInstance GetInstance(UUID itemID)
1328 { 1408 {
1329 IScriptInstance instance; 1409 IScriptInstance instance;
1330 lock (m_Scripts) 1410 lockScriptsForRead(true);
1411 if (!m_Scripts.ContainsKey(itemID))
1331 { 1412 {
1332 if (!m_Scripts.ContainsKey(itemID)) 1413 lockScriptsForRead(false);
1333 return null; 1414 return null;
1334 instance = m_Scripts[itemID];
1335 } 1415 }
1416 instance = m_Scripts[itemID];
1417 lockScriptsForRead(false);
1336 return instance; 1418 return instance;
1337 } 1419 }
1338 1420
@@ -1356,6 +1438,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1356 return false; 1438 return false;
1357 } 1439 }
1358 1440
1441 [DebuggerNonUserCode]
1359 public void ApiResetScript(UUID itemID) 1442 public void ApiResetScript(UUID itemID)
1360 { 1443 {
1361 IScriptInstance instance = GetInstance(itemID); 1444 IScriptInstance instance = GetInstance(itemID);
@@ -1407,6 +1490,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1407 return UUID.Zero; 1490 return UUID.Zero;
1408 } 1491 }
1409 1492
1493 [DebuggerNonUserCode]
1410 public void SetState(UUID itemID, string newState) 1494 public void SetState(UUID itemID, string newState)
1411 { 1495 {
1412 IScriptInstance instance = GetInstance(itemID); 1496 IScriptInstance instance = GetInstance(itemID);
@@ -1427,11 +1511,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1427 { 1511 {
1428 List<IScriptInstance> instances = new List<IScriptInstance>(); 1512 List<IScriptInstance> instances = new List<IScriptInstance>();
1429 1513
1430 lock (m_Scripts) 1514 lockScriptsForRead(true);
1431 { 1515 foreach (IScriptInstance instance in m_Scripts.Values)
1432 foreach (IScriptInstance instance in m_Scripts.Values)
1433 instances.Add(instance); 1516 instances.Add(instance);
1434 } 1517 lockScriptsForRead(false);
1435 1518
1436 foreach (IScriptInstance i in instances) 1519 foreach (IScriptInstance i in instances)
1437 { 1520 {
@@ -1808,5 +1891,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1808 if (instance != null) 1891 if (instance != null)
1809 instance.Resume(); 1892 instance.Resume();
1810 } 1893 }
1894
1895 public bool HasScript(UUID itemID, out bool running)
1896 {
1897 running = true;
1898
1899 IScriptInstance instance = GetInstance(itemID);
1900 if (instance == null)
1901 return false;
1902
1903 running = instance.Running;
1904 return true;
1905 }
1811 } 1906 }
1812} \ No newline at end of file 1907} \ No newline at end of file