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.cs356
1 files changed, 222 insertions, 134 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index f6afcdb..c437703 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,46 +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 m_log.InfoFormat( 343 // Force a final state save
275 "[XEngine]: Shutting down {0} scripts in {1}", m_Scripts.Count, m_Scene.RegionInfo.RegionName); 344 //
276 345 if (m_Assemblies.ContainsKey(instance.AssetID))
277 foreach (IScriptInstance instance in m_Scripts.Values)
278 { 346 {
279 // Force a final state save 347 string assembly = m_Assemblies[instance.AssetID];
280 // 348 instance.SaveState(assembly);
281 if (m_Assemblies.ContainsKey(instance.AssetID)) 349 }
282 {
283 string assembly = m_Assemblies[instance.AssetID];
284 instance.SaveState(assembly);
285 }
286 350
287 // Clear the event queue and abort the instance thread 351 // Clear the event queue and abort the instance thread
288 // 352 //
289 instance.ClearQueue(); 353 instance.ClearQueue();
290 instance.Stop(0); 354 instance.Stop(0);
291 355
292 // Release events, timer, etc 356 // Release events, timer, etc
293 // 357 //
294 instance.DestroyScriptInstance(); 358 instance.DestroyScriptInstance();
295 359
296 // Unload scripts and app domains 360 // Unload scripts and app domains
297 // Must be done explicitly because they have infinite 361 // Must be done explicitly because they have infinite
298 // lifetime 362 // lifetime
299 // 363 //
300 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 364 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
301 if (m_DomainScripts[instance.AppDomain].Count == 0) 365 if (m_DomainScripts[instance.AppDomain].Count == 0)
302 { 366 {
303 m_DomainScripts.Remove(instance.AppDomain); 367 m_DomainScripts.Remove(instance.AppDomain);
304 UnloadAppDomain(instance.AppDomain); 368 UnloadAppDomain(instance.AppDomain);
305 }
306 } 369 }
307 m_Scripts.Clear();
308 m_PrimObjects.Clear();
309 m_Assemblies.Clear();
310 m_DomainScripts.Clear();
311 } 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
312 lock (m_ScriptEngines) 379 lock (m_ScriptEngines)
313 { 380 {
314 m_ScriptEngines.Remove(this); 381 m_ScriptEngines.Remove(this);
@@ -370,22 +437,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
370 437
371 List<IScriptInstance> instances = new List<IScriptInstance>(); 438 List<IScriptInstance> instances = new List<IScriptInstance>();
372 439
373 lock (m_Scripts) 440 lockScriptsForRead(true);
374 { 441 foreach (IScriptInstance instance in m_Scripts.Values)
375 foreach (IScriptInstance instance in m_Scripts.Values)
376 instances.Add(instance); 442 instances.Add(instance);
377 } 443 lockScriptsForRead(false);
378 444
379 foreach (IScriptInstance i in instances) 445 foreach (IScriptInstance i in instances)
380 { 446 {
381 string assembly = String.Empty; 447 string assembly = String.Empty;
382 448
383 lock (m_Scripts) 449
384 {
385 if (!m_Assemblies.ContainsKey(i.AssetID)) 450 if (!m_Assemblies.ContainsKey(i.AssetID))
386 continue; 451 continue;
387 assembly = m_Assemblies[i.AssetID]; 452 assembly = m_Assemblies[i.AssetID];
388 } 453
389 454
390 i.SaveState(assembly); 455 i.SaveState(assembly);
391 } 456 }
@@ -719,92 +784,95 @@ namespace OpenSim.Region.ScriptEngine.XEngine
719 } 784 }
720 785
721 ScriptInstance instance = null; 786 ScriptInstance instance = null;
722 lock (m_Scripts) 787 // Create the object record
788 lockScriptsForRead(true);
789 if ((!m_Scripts.ContainsKey(itemID)) ||
790 (m_Scripts[itemID].AssetID != assetID))
723 { 791 {
724 // Create the object record 792 lockScriptsForRead(false);
725 793
726 if ((!m_Scripts.ContainsKey(itemID)) || 794 UUID appDomain = assetID;
727 (m_Scripts[itemID].AssetID != assetID))
728 {
729 UUID appDomain = assetID;
730 795
731 if (part.ParentGroup.IsAttachment) 796 if (part.ParentGroup.IsAttachment)
732 appDomain = part.ParentGroup.RootPart.UUID; 797 appDomain = part.ParentGroup.RootPart.UUID;
733 798
734 if (!m_AppDomains.ContainsKey(appDomain)) 799 if (!m_AppDomains.ContainsKey(appDomain))
800 {
801 try
735 { 802 {
736 try 803 AppDomainSetup appSetup = new AppDomainSetup();
737 { 804 appSetup.PrivateBinPath = Path.Combine(
738 AppDomainSetup appSetup = new AppDomainSetup(); 805 m_ScriptEnginesPath,
739 appSetup.PrivateBinPath = Path.Combine( 806 m_Scene.RegionInfo.RegionID.ToString());
740 m_ScriptEnginesPath, 807
741 m_Scene.RegionInfo.RegionID.ToString()); 808 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
742 809 Evidence evidence = new Evidence(baseEvidence);
743 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 810
744 Evidence evidence = new Evidence(baseEvidence); 811 AppDomain sandbox;
745 812 if (m_AppDomainLoading)
746 AppDomain sandbox; 813 sandbox = AppDomain.CreateDomain(
747 if (m_AppDomainLoading) 814 m_Scene.RegionInfo.RegionID.ToString(),
748 sandbox = AppDomain.CreateDomain( 815 evidence, appSetup);
749 m_Scene.RegionInfo.RegionID.ToString(), 816 else
750 evidence, appSetup); 817 sandbox = AppDomain.CurrentDomain;
751 else 818
752 sandbox = AppDomain.CurrentDomain; 819 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
753 820 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
754 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); 821 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
755 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); 822 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
756 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet"); 823 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
757 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet); 824 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
758 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement); 825 //sandbox.SetAppDomainPolicy(sandboxPolicy);
759 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup; 826
760 //sandbox.SetAppDomainPolicy(sandboxPolicy); 827 m_AppDomains[appDomain] = sandbox;
761 828
762 m_AppDomains[appDomain] = sandbox; 829 m_AppDomains[appDomain].AssemblyResolve +=
763 830 new ResolveEventHandler(
764 m_AppDomains[appDomain].AssemblyResolve += 831 AssemblyResolver.OnAssemblyResolve);
765 new ResolveEventHandler( 832 m_DomainScripts[appDomain] = new List<UUID>();
766 AssemblyResolver.OnAssemblyResolve); 833 }
767 m_DomainScripts[appDomain] = new List<UUID>(); 834 catch (Exception e)
768 } 835 {
769 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)
770 { 840 {
771 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); 841 m_AddingAssemblies[assembly]--;
772 m_ScriptErrorMessage += "Exception creating app domain:\n";
773 m_ScriptFailCount++;
774 lock (m_AddingAssemblies)
775 {
776 m_AddingAssemblies[assembly]--;
777 }
778 return false;
779 } 842 }
843 return false;
780 } 844 }
781 m_DomainScripts[appDomain].Add(itemID); 845 }
782 846 m_DomainScripts[appDomain].Add(itemID);
783 instance = new ScriptInstance(this, part, 847
784 itemID, assetID, assembly, 848 instance = new ScriptInstance(this, part,
785 m_AppDomains[appDomain], 849 itemID, assetID, assembly,
786 part.ParentGroup.RootPart.Name, 850 m_AppDomains[appDomain],
787 item.Name, startParam, postOnRez, 851 part.ParentGroup.RootPart.Name,
788 stateSource, m_MaxScriptQueue); 852 item.Name, startParam, postOnRez,
789 853 stateSource, m_MaxScriptQueue);
790 m_log.DebugFormat( 854
855 m_log.DebugFormat(
791 "[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}",
792 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, 857 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
793 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); 858 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
794 859
795 if (presence != null) 860 if (presence != null)
796 { 861 {
797 ShowScriptSaveResponse(item.OwnerID, 862 ShowScriptSaveResponse(item.OwnerID,
798 assetID, "Compile successful", true); 863 assetID, "Compile successful", true);
799 }
800
801 instance.AppDomain = appDomain;
802 instance.LineMap = linemap;
803
804 m_Scripts[itemID] = instance;
805 } 864 }
806 }
807 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 }
808 lock (m_PrimObjects) 876 lock (m_PrimObjects)
809 { 877 {
810 if (!m_PrimObjects.ContainsKey(localID)) 878 if (!m_PrimObjects.ContainsKey(localID))
@@ -823,9 +891,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
823 m_AddingAssemblies[assembly]--; 891 m_AddingAssemblies[assembly]--;
824 } 892 }
825 893
826 if (instance != null) 894 if (instance!=null)
827 instance.Init(); 895 instance.Init();
828 896
829 return true; 897 return true;
830 } 898 }
831 899
@@ -838,20 +906,23 @@ namespace OpenSim.Region.ScriptEngine.XEngine
838 m_CompileDict.Remove(itemID); 906 m_CompileDict.Remove(itemID);
839 } 907 }
840 908
841 IScriptInstance instance = null; 909 lockScriptsForRead(true);
842 910 // Do we even have it?
843 lock (m_Scripts) 911 if (!m_Scripts.ContainsKey(itemID))
844 { 912 {
845 // Do we even have it? 913 lockScriptsForRead(false);
846 if (!m_Scripts.ContainsKey(itemID)) 914 return;
847 return;
848
849 instance=m_Scripts[itemID];
850 m_Scripts.Remove(itemID);
851 } 915 }
916
852 917
918 IScriptInstance instance=m_Scripts[itemID];
919 lockScriptsForRead(false);
920 lockScriptsForWrite(true);
921 m_Scripts.Remove(itemID);
922 lockScriptsForWrite(false);
853 instance.ClearQueue(); 923 instance.ClearQueue();
854 instance.Stop(0); 924 instance.Stop(0);
925
855// bool objectRemoved = false; 926// bool objectRemoved = false;
856 927
857 lock (m_PrimObjects) 928 lock (m_PrimObjects)
@@ -887,11 +958,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
887 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 958 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
888 if (handlerObjectRemoved != null) 959 if (handlerObjectRemoved != null)
889 { 960 {
890 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID); 961 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
891 handlerObjectRemoved(part.UUID); 962 handlerObjectRemoved(part.UUID);
892 } 963 }
893 964
894 965 CleanAssemblies();
966
895 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 967 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
896 if (handlerScriptRemoved != null) 968 if (handlerScriptRemoved != null)
897 handlerScriptRemoved(itemID); 969 handlerScriptRemoved(itemID);
@@ -1033,7 +1105,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1033 return false; 1105 return false;
1034 1106
1035 uuids = m_PrimObjects[localID]; 1107 uuids = m_PrimObjects[localID];
1036 } 1108
1037 1109
1038 foreach (UUID itemID in uuids) 1110 foreach (UUID itemID in uuids)
1039 { 1111 {
@@ -1051,6 +1123,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1051 result = true; 1123 result = true;
1052 } 1124 }
1053 } 1125 }
1126 }
1054 1127
1055 return result; 1128 return result;
1056 } 1129 }
@@ -1150,12 +1223,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1150 private IScriptInstance GetInstance(UUID itemID) 1223 private IScriptInstance GetInstance(UUID itemID)
1151 { 1224 {
1152 IScriptInstance instance; 1225 IScriptInstance instance;
1153 lock (m_Scripts) 1226 lockScriptsForRead(true);
1227 if (!m_Scripts.ContainsKey(itemID))
1154 { 1228 {
1155 if (!m_Scripts.ContainsKey(itemID)) 1229 lockScriptsForRead(false);
1156 return null; 1230 return null;
1157 instance = m_Scripts[itemID];
1158 } 1231 }
1232 instance = m_Scripts[itemID];
1233 lockScriptsForRead(false);
1159 return instance; 1234 return instance;
1160 } 1235 }
1161 1236
@@ -1179,6 +1254,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1179 return false; 1254 return false;
1180 } 1255 }
1181 1256
1257 [DebuggerNonUserCode]
1182 public void ApiResetScript(UUID itemID) 1258 public void ApiResetScript(UUID itemID)
1183 { 1259 {
1184 IScriptInstance instance = GetInstance(itemID); 1260 IScriptInstance instance = GetInstance(itemID);
@@ -1230,6 +1306,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1230 return UUID.Zero; 1306 return UUID.Zero;
1231 } 1307 }
1232 1308
1309 [DebuggerNonUserCode]
1233 public void SetState(UUID itemID, string newState) 1310 public void SetState(UUID itemID, string newState)
1234 { 1311 {
1235 IScriptInstance instance = GetInstance(itemID); 1312 IScriptInstance instance = GetInstance(itemID);
@@ -1250,11 +1327,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1250 { 1327 {
1251 List<IScriptInstance> instances = new List<IScriptInstance>(); 1328 List<IScriptInstance> instances = new List<IScriptInstance>();
1252 1329
1253 lock (m_Scripts) 1330 lockScriptsForRead(true);
1254 { 1331 foreach (IScriptInstance instance in m_Scripts.Values)
1255 foreach (IScriptInstance instance in m_Scripts.Values)
1256 instances.Add(instance); 1332 instances.Add(instance);
1257 } 1333 lockScriptsForRead(false);
1258 1334
1259 foreach (IScriptInstance i in instances) 1335 foreach (IScriptInstance i in instances)
1260 { 1336 {
@@ -1635,5 +1711,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1635 1711
1636 instance.Resume(); 1712 instance.Resume();
1637 } 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 }
1638 } 1726 }
1639} 1727}