aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs353
1 files changed, 222 insertions, 131 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 156fd57..975e9cc 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;
@@ -102,6 +103,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
102 private Dictionary<UUID, IScriptInstance> m_Scripts = 103 private Dictionary<UUID, IScriptInstance> m_Scripts =
103 new Dictionary<UUID, IScriptInstance>(); 104 new Dictionary<UUID, IScriptInstance>();
104 105
106 private OpenMetaverse.ReaderWriterLockSlim m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
107
105 // Maps the asset ID to the assembly 108 // Maps the asset ID to the assembly
106 109
107 private Dictionary<UUID, string> m_Assemblies = 110 private Dictionary<UUID, string> m_Assemblies =
@@ -124,6 +127,71 @@ namespace OpenSim.Region.ScriptEngine.XEngine
124 IWorkItemResult m_CurrentCompile = null; 127 IWorkItemResult m_CurrentCompile = null;
125 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>(); 128 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>();
126 129
130 private void lockScriptsForRead(bool locked)
131 {
132 if (locked)
133 {
134 if (m_scriptsLock.RecursiveReadCount > 0)
135 {
136 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.");
137 m_scriptsLock.ExitReadLock();
138 }
139 if (m_scriptsLock.RecursiveWriteCount > 0)
140 {
141 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
142 m_scriptsLock.ExitWriteLock();
143 }
144
145 while (!m_scriptsLock.TryEnterReadLock(60000))
146 {
147 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.");
148 if (m_scriptsLock.IsWriteLockHeld)
149 {
150 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
151 }
152 }
153 }
154 else
155 {
156 if (m_scriptsLock.RecursiveReadCount > 0)
157 {
158 m_scriptsLock.ExitReadLock();
159 }
160 }
161 }
162 private void lockScriptsForWrite(bool locked)
163 {
164 if (locked)
165 {
166 if (m_scriptsLock.RecursiveReadCount > 0)
167 {
168 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.");
169 m_scriptsLock.ExitReadLock();
170 }
171 if (m_scriptsLock.RecursiveWriteCount > 0)
172 {
173 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
174 m_scriptsLock.ExitWriteLock();
175 }
176
177 while (!m_scriptsLock.TryEnterWriteLock(60000))
178 {
179 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.");
180 if (m_scriptsLock.IsWriteLockHeld)
181 {
182 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
183 }
184 }
185 }
186 else
187 {
188 if (m_scriptsLock.RecursiveWriteCount > 0)
189 {
190 m_scriptsLock.ExitWriteLock();
191 }
192 }
193 }
194
127 public string ScriptEngineName 195 public string ScriptEngineName
128 { 196 {
129 get { return "XEngine"; } 197 get { return "XEngine"; }
@@ -269,43 +337,45 @@ namespace OpenSim.Region.ScriptEngine.XEngine
269 337
270 public void RemoveRegion(Scene scene) 338 public void RemoveRegion(Scene scene)
271 { 339 {
272 lock (m_Scripts) 340 lockScriptsForRead(true);
341 foreach (IScriptInstance instance in m_Scripts.Values)
273 { 342 {
274 foreach (IScriptInstance instance in m_Scripts.Values) 343 // Force a final state save
344 //
345 if (m_Assemblies.ContainsKey(instance.AssetID))
275 { 346 {
276 // Force a final state save 347 string assembly = m_Assemblies[instance.AssetID];
277 // 348 instance.SaveState(assembly);
278 if (m_Assemblies.ContainsKey(instance.AssetID)) 349 }
279 {
280 string assembly = m_Assemblies[instance.AssetID];
281 instance.SaveState(assembly);
282 }
283 350
284 // Clear the event queue and abort the instance thread 351 // Clear the event queue and abort the instance thread
285 // 352 //
286 instance.ClearQueue(); 353 instance.ClearQueue();
287 instance.Stop(0); 354 instance.Stop(0);
288 355
289 // Release events, timer, etc 356 // Release events, timer, etc
290 // 357 //
291 instance.DestroyScriptInstance(); 358 instance.DestroyScriptInstance();
292 359
293 // Unload scripts and app domains 360 // Unload scripts and app domains
294 // Must be done explicitly because they have infinite 361 // Must be done explicitly because they have infinite
295 // lifetime 362 // lifetime
296 // 363 //
297 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 364 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
298 if (m_DomainScripts[instance.AppDomain].Count == 0) 365 if (m_DomainScripts[instance.AppDomain].Count == 0)
299 { 366 {
300 m_DomainScripts.Remove(instance.AppDomain); 367 m_DomainScripts.Remove(instance.AppDomain);
301 UnloadAppDomain(instance.AppDomain); 368 UnloadAppDomain(instance.AppDomain);
302 }
303 } 369 }
304 m_Scripts.Clear();
305 m_PrimObjects.Clear();
306 m_Assemblies.Clear();
307 m_DomainScripts.Clear();
308 } 370 }
371 lockScriptsForRead(false);
372 lockScriptsForWrite(true);
373 m_Scripts.Clear();
374 lockScriptsForWrite(false);
375 m_PrimObjects.Clear();
376 m_Assemblies.Clear();
377 m_DomainScripts.Clear();
378
309 lock (m_ScriptEngines) 379 lock (m_ScriptEngines)
310 { 380 {
311 m_ScriptEngines.Remove(this); 381 m_ScriptEngines.Remove(this);
@@ -367,22 +437,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
367 437
368 List<IScriptInstance> instances = new List<IScriptInstance>(); 438 List<IScriptInstance> instances = new List<IScriptInstance>();
369 439
370 lock (m_Scripts) 440 lockScriptsForRead(true);
371 { 441 foreach (IScriptInstance instance in m_Scripts.Values)
372 foreach (IScriptInstance instance in m_Scripts.Values)
373 instances.Add(instance); 442 instances.Add(instance);
374 } 443 lockScriptsForRead(false);
375 444
376 foreach (IScriptInstance i in instances) 445 foreach (IScriptInstance i in instances)
377 { 446 {
378 string assembly = String.Empty; 447 string assembly = String.Empty;
379 448
380 lock (m_Scripts) 449
381 {
382 if (!m_Assemblies.ContainsKey(i.AssetID)) 450 if (!m_Assemblies.ContainsKey(i.AssetID))
383 continue; 451 continue;
384 assembly = m_Assemblies[i.AssetID]; 452 assembly = m_Assemblies[i.AssetID];
385 } 453
386 454
387 i.SaveState(assembly); 455 i.SaveState(assembly);
388 } 456 }
@@ -716,92 +784,95 @@ namespace OpenSim.Region.ScriptEngine.XEngine
716 } 784 }
717 785
718 ScriptInstance instance = null; 786 ScriptInstance instance = null;
719 lock (m_Scripts) 787 // Create the object record
788 lockScriptsForRead(true);
789 if ((!m_Scripts.ContainsKey(itemID)) ||
790 (m_Scripts[itemID].AssetID != assetID))
720 { 791 {
721 // Create the object record 792 lockScriptsForRead(false);
722 793
723 if ((!m_Scripts.ContainsKey(itemID)) || 794 UUID appDomain = assetID;
724 (m_Scripts[itemID].AssetID != assetID))
725 {
726 UUID appDomain = assetID;
727 795
728 if (part.ParentGroup.IsAttachment) 796 if (part.ParentGroup.IsAttachment)
729 appDomain = part.ParentGroup.RootPart.UUID; 797 appDomain = part.ParentGroup.RootPart.UUID;
730 798
731 if (!m_AppDomains.ContainsKey(appDomain)) 799 if (!m_AppDomains.ContainsKey(appDomain))
800 {
801 try
732 { 802 {
733 try 803 AppDomainSetup appSetup = new AppDomainSetup();
734 { 804 appSetup.PrivateBinPath = Path.Combine(
735 AppDomainSetup appSetup = new AppDomainSetup(); 805 m_ScriptEnginesPath,
736 appSetup.PrivateBinPath = Path.Combine( 806 m_Scene.RegionInfo.RegionID.ToString());
737 m_ScriptEnginesPath, 807
738 m_Scene.RegionInfo.RegionID.ToString()); 808 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
739 809 Evidence evidence = new Evidence(baseEvidence);
740 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 810
741 Evidence evidence = new Evidence(baseEvidence); 811 AppDomain sandbox;
742 812 if (m_AppDomainLoading)
743 AppDomain sandbox; 813 sandbox = AppDomain.CreateDomain(
744 if (m_AppDomainLoading) 814 m_Scene.RegionInfo.RegionID.ToString(),
745 sandbox = AppDomain.CreateDomain( 815 evidence, appSetup);
746 m_Scene.RegionInfo.RegionID.ToString(), 816 else
747 evidence, appSetup); 817 sandbox = AppDomain.CurrentDomain;
748 else 818
749 sandbox = AppDomain.CurrentDomain; 819 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
750 820 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
751 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); 821 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
752 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); 822 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
753 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet"); 823 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
754 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet); 824 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
755 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement); 825 //sandbox.SetAppDomainPolicy(sandboxPolicy);
756 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup; 826
757 //sandbox.SetAppDomainPolicy(sandboxPolicy); 827 m_AppDomains[appDomain] = sandbox;
758 828
759 m_AppDomains[appDomain] = sandbox; 829 m_AppDomains[appDomain].AssemblyResolve +=
760 830 new ResolveEventHandler(
761 m_AppDomains[appDomain].AssemblyResolve += 831 AssemblyResolver.OnAssemblyResolve);
762 new ResolveEventHandler( 832 m_DomainScripts[appDomain] = new List<UUID>();
763 AssemblyResolver.OnAssemblyResolve); 833 }
764 m_DomainScripts[appDomain] = new List<UUID>(); 834 catch (Exception e)
765 } 835 {
766 catch (Exception e) 836 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
837 m_ScriptErrorMessage += "Exception creating app domain:\n";
838 m_ScriptFailCount++;
839 lock (m_AddingAssemblies)
767 { 840 {
768 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); 841 m_AddingAssemblies[assembly]--;
769 m_ScriptErrorMessage += "Exception creating app domain:\n";
770 m_ScriptFailCount++;
771 lock (m_AddingAssemblies)
772 {
773 m_AddingAssemblies[assembly]--;
774 }
775 return false;
776 } 842 }
843 return false;
777 } 844 }
778 m_DomainScripts[appDomain].Add(itemID); 845 }
779 846 m_DomainScripts[appDomain].Add(itemID);
780 instance = new ScriptInstance(this, part, 847
781 itemID, assetID, assembly, 848 instance = new ScriptInstance(this, part,
782 m_AppDomains[appDomain], 849 itemID, assetID, assembly,
783 part.ParentGroup.RootPart.Name, 850 m_AppDomains[appDomain],
784 item.Name, startParam, postOnRez, 851 part.ParentGroup.RootPart.Name,
785 stateSource, m_MaxScriptQueue); 852 item.Name, startParam, postOnRez,
786 853 stateSource, m_MaxScriptQueue);
787 m_log.DebugFormat( 854
855 m_log.DebugFormat(
788 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}", 856 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
789 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, 857 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
790 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); 858 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
791 859
792 if (presence != null) 860 if (presence != null)
793 { 861 {
794 ShowScriptSaveResponse(item.OwnerID, 862 ShowScriptSaveResponse(item.OwnerID,
795 assetID, "Compile successful", true); 863 assetID, "Compile successful", true);
796 }
797
798 instance.AppDomain = appDomain;
799 instance.LineMap = linemap;
800
801 m_Scripts[itemID] = instance;
802 } 864 }
803 }
804 865
866 instance.AppDomain = appDomain;
867 instance.LineMap = linemap;
868 lockScriptsForWrite(true);
869 m_Scripts[itemID] = instance;
870 lockScriptsForWrite(false);
871 }
872 else
873 {
874 lockScriptsForRead(false);
875 }
805 lock (m_PrimObjects) 876 lock (m_PrimObjects)
806 { 877 {
807 if (!m_PrimObjects.ContainsKey(localID)) 878 if (!m_PrimObjects.ContainsKey(localID))
@@ -820,9 +891,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
820 m_AddingAssemblies[assembly]--; 891 m_AddingAssemblies[assembly]--;
821 } 892 }
822 893
823 if (instance != null) 894 if (instance!=null)
824 instance.Init(); 895 instance.Init();
825 896
826 return true; 897 return true;
827 } 898 }
828 899
@@ -835,20 +906,23 @@ namespace OpenSim.Region.ScriptEngine.XEngine
835 m_CompileDict.Remove(itemID); 906 m_CompileDict.Remove(itemID);
836 } 907 }
837 908
838 IScriptInstance instance = null; 909 lockScriptsForRead(true);
839 910 // Do we even have it?
840 lock (m_Scripts) 911 if (!m_Scripts.ContainsKey(itemID))
841 { 912 {
842 // Do we even have it? 913 lockScriptsForRead(false);
843 if (!m_Scripts.ContainsKey(itemID)) 914 return;
844 return;
845
846 instance=m_Scripts[itemID];
847 m_Scripts.Remove(itemID);
848 } 915 }
916
849 917
918 IScriptInstance instance=m_Scripts[itemID];
919 lockScriptsForRead(false);
920 lockScriptsForWrite(true);
921 m_Scripts.Remove(itemID);
922 lockScriptsForWrite(false);
850 instance.ClearQueue(); 923 instance.ClearQueue();
851 instance.Stop(0); 924 instance.Stop(0);
925
852// bool objectRemoved = false; 926// bool objectRemoved = false;
853 927
854 lock (m_PrimObjects) 928 lock (m_PrimObjects)
@@ -884,11 +958,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
884 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 958 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
885 if (handlerObjectRemoved != null) 959 if (handlerObjectRemoved != null)
886 { 960 {
887 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID); 961 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
888 handlerObjectRemoved(part.UUID); 962 handlerObjectRemoved(part.UUID);
889 } 963 }
890 964
891 965 CleanAssemblies();
966
892 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 967 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
893 if (handlerScriptRemoved != null) 968 if (handlerScriptRemoved != null)
894 handlerScriptRemoved(itemID); 969 handlerScriptRemoved(itemID);
@@ -1030,7 +1105,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1030 return false; 1105 return false;
1031 1106
1032 uuids = m_PrimObjects[localID]; 1107 uuids = m_PrimObjects[localID];
1033 } 1108
1034 1109
1035 foreach (UUID itemID in uuids) 1110 foreach (UUID itemID in uuids)
1036 { 1111 {
@@ -1048,6 +1123,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1048 result = true; 1123 result = true;
1049 } 1124 }
1050 } 1125 }
1126 }
1051 1127
1052 return result; 1128 return result;
1053 } 1129 }
@@ -1147,12 +1223,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1147 private IScriptInstance GetInstance(UUID itemID) 1223 private IScriptInstance GetInstance(UUID itemID)
1148 { 1224 {
1149 IScriptInstance instance; 1225 IScriptInstance instance;
1150 lock (m_Scripts) 1226 lockScriptsForRead(true);
1227 if (!m_Scripts.ContainsKey(itemID))
1151 { 1228 {
1152 if (!m_Scripts.ContainsKey(itemID)) 1229 lockScriptsForRead(false);
1153 return null; 1230 return null;
1154 instance = m_Scripts[itemID];
1155 } 1231 }
1232 instance = m_Scripts[itemID];
1233 lockScriptsForRead(false);
1156 return instance; 1234 return instance;
1157 } 1235 }
1158 1236
@@ -1176,6 +1254,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1176 return false; 1254 return false;
1177 } 1255 }
1178 1256
1257 [DebuggerNonUserCode]
1179 public void ApiResetScript(UUID itemID) 1258 public void ApiResetScript(UUID itemID)
1180 { 1259 {
1181 IScriptInstance instance = GetInstance(itemID); 1260 IScriptInstance instance = GetInstance(itemID);
@@ -1227,6 +1306,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1227 return UUID.Zero; 1306 return UUID.Zero;
1228 } 1307 }
1229 1308
1309 [DebuggerNonUserCode]
1230 public void SetState(UUID itemID, string newState) 1310 public void SetState(UUID itemID, string newState)
1231 { 1311 {
1232 IScriptInstance instance = GetInstance(itemID); 1312 IScriptInstance instance = GetInstance(itemID);
@@ -1247,11 +1327,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1247 { 1327 {
1248 List<IScriptInstance> instances = new List<IScriptInstance>(); 1328 List<IScriptInstance> instances = new List<IScriptInstance>();
1249 1329
1250 lock (m_Scripts) 1330 lockScriptsForRead(true);
1251 { 1331 foreach (IScriptInstance instance in m_Scripts.Values)
1252 foreach (IScriptInstance instance in m_Scripts.Values)
1253 instances.Add(instance); 1332 instances.Add(instance);
1254 } 1333 lockScriptsForRead(false);
1255 1334
1256 foreach (IScriptInstance i in instances) 1335 foreach (IScriptInstance i in instances)
1257 { 1336 {
@@ -1632,5 +1711,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1632 1711
1633 instance.Resume(); 1712 instance.Resume();
1634 } 1713 }
1714
1715 public bool HasScript(UUID itemID, out bool running)
1716 {
1717 running = true;
1718
1719 IScriptInstance instance = GetInstance(itemID);
1720 if (instance == null)
1721 return false;
1722
1723 running = instance.Running;
1724 return true;
1725 }
1635 } 1726 }
1636} 1727}