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.cs422
1 files changed, 252 insertions, 170 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 61a2088..30e127d 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"; }
@@ -263,43 +331,45 @@ namespace OpenSim.Region.ScriptEngine.XEngine
263 331
264 public void RemoveRegion(Scene scene) 332 public void RemoveRegion(Scene scene)
265 { 333 {
266 lock (m_Scripts) 334 lockScriptsForRead(true);
335 foreach (IScriptInstance instance in m_Scripts.Values)
267 { 336 {
268 foreach (IScriptInstance instance in m_Scripts.Values) 337 // Force a final state save
338 //
339 if (m_Assemblies.ContainsKey(instance.AssetID))
269 { 340 {
270 // Force a final state save 341 string assembly = m_Assemblies[instance.AssetID];
271 // 342 instance.SaveState(assembly);
272 if (m_Assemblies.ContainsKey(instance.AssetID)) 343 }
273 {
274 string assembly = m_Assemblies[instance.AssetID];
275 instance.SaveState(assembly);
276 }
277 344
278 // Clear the event queue and abort the instance thread 345 // Clear the event queue and abort the instance thread
279 // 346 //
280 instance.ClearQueue(); 347 instance.ClearQueue();
281 instance.Stop(0); 348 instance.Stop(0);
282 349
283 // Release events, timer, etc 350 // Release events, timer, etc
284 // 351 //
285 instance.DestroyScriptInstance(); 352 instance.DestroyScriptInstance();
286 353
287 // Unload scripts and app domains 354 // Unload scripts and app domains
288 // Must be done explicitly because they have infinite 355 // Must be done explicitly because they have infinite
289 // lifetime 356 // lifetime
290 // 357 //
291 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 358 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
292 if (m_DomainScripts[instance.AppDomain].Count == 0) 359 if (m_DomainScripts[instance.AppDomain].Count == 0)
293 { 360 {
294 m_DomainScripts.Remove(instance.AppDomain); 361 m_DomainScripts.Remove(instance.AppDomain);
295 UnloadAppDomain(instance.AppDomain); 362 UnloadAppDomain(instance.AppDomain);
296 }
297 } 363 }
298 m_Scripts.Clear();
299 m_PrimObjects.Clear();
300 m_Assemblies.Clear();
301 m_DomainScripts.Clear();
302 } 364 }
365 lockScriptsForRead(false);
366 lockScriptsForWrite(true);
367 m_Scripts.Clear();
368 lockScriptsForWrite(false);
369 m_PrimObjects.Clear();
370 m_Assemblies.Clear();
371 m_DomainScripts.Clear();
372
303 lock (m_ScriptEngines) 373 lock (m_ScriptEngines)
304 { 374 {
305 m_ScriptEngines.Remove(this); 375 m_ScriptEngines.Remove(this);
@@ -358,22 +428,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
358 428
359 List<IScriptInstance> instances = new List<IScriptInstance>(); 429 List<IScriptInstance> instances = new List<IScriptInstance>();
360 430
361 lock (m_Scripts) 431 lockScriptsForRead(true);
362 { 432 foreach (IScriptInstance instance in m_Scripts.Values)
363 foreach (IScriptInstance instance in m_Scripts.Values)
364 instances.Add(instance); 433 instances.Add(instance);
365 } 434 lockScriptsForRead(false);
366 435
367 foreach (IScriptInstance i in instances) 436 foreach (IScriptInstance i in instances)
368 { 437 {
369 string assembly = String.Empty; 438 string assembly = String.Empty;
370 439
371 lock (m_Scripts) 440
372 {
373 if (!m_Assemblies.ContainsKey(i.AssetID)) 441 if (!m_Assemblies.ContainsKey(i.AssetID))
374 continue; 442 continue;
375 assembly = m_Assemblies[i.AssetID]; 443 assembly = m_Assemblies[i.AssetID];
376 } 444
377 445
378 i.SaveState(assembly); 446 i.SaveState(assembly);
379 } 447 }
@@ -696,111 +764,117 @@ namespace OpenSim.Region.ScriptEngine.XEngine
696 } 764 }
697 } 765 }
698 766
699 lock (m_Scripts) 767
768
769 ScriptInstance instance = null;
770 // Create the object record
771 lockScriptsForRead(true);
772 if ((!m_Scripts.ContainsKey(itemID)) ||
773 (m_Scripts[itemID].AssetID != assetID))
700 { 774 {
701 ScriptInstance instance = null; 775 lockScriptsForRead(false);
702 // Create the object record
703 776
704 if ((!m_Scripts.ContainsKey(itemID)) || 777 UUID appDomain = assetID;
705 (m_Scripts[itemID].AssetID != assetID))
706 {
707 UUID appDomain = assetID;
708 778
709 if (part.ParentGroup.IsAttachment) 779 if (part.ParentGroup.IsAttachment)
710 appDomain = part.ParentGroup.RootPart.UUID; 780 appDomain = part.ParentGroup.RootPart.UUID;
711 781
712 if (!m_AppDomains.ContainsKey(appDomain)) 782 if (!m_AppDomains.ContainsKey(appDomain))
783 {
784 try
713 { 785 {
714 try 786 AppDomainSetup appSetup = new AppDomainSetup();
715 { 787 // appSetup.ApplicationBase = Path.Combine(
716 AppDomainSetup appSetup = new AppDomainSetup(); 788 // "ScriptEngines",
717// appSetup.ApplicationBase = Path.Combine( 789 // m_Scene.RegionInfo.RegionID.ToString());
718// "ScriptEngines", 790
719// m_Scene.RegionInfo.RegionID.ToString()); 791 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
720 792 Evidence evidence = new Evidence(baseEvidence);
721 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 793
722 Evidence evidence = new Evidence(baseEvidence); 794 AppDomain sandbox;
723 795 if (m_AppDomainLoading)
724 AppDomain sandbox; 796 sandbox = AppDomain.CreateDomain(
725 if (m_AppDomainLoading) 797 m_Scene.RegionInfo.RegionID.ToString(),
726 sandbox = AppDomain.CreateDomain( 798 evidence, appSetup);
727 m_Scene.RegionInfo.RegionID.ToString(), 799 else
728 evidence, appSetup); 800 sandbox = AppDomain.CurrentDomain;
729 else 801
730 sandbox = AppDomain.CurrentDomain; 802 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
731 803 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
732 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); 804 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
733 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); 805 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
734 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet"); 806 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
735 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet); 807 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
736 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement); 808 //sandbox.SetAppDomainPolicy(sandboxPolicy);
737 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup; 809
738 //sandbox.SetAppDomainPolicy(sandboxPolicy); 810 m_AppDomains[appDomain] = sandbox;
739 811
740 m_AppDomains[appDomain] = sandbox; 812 m_AppDomains[appDomain].AssemblyResolve +=
741 813 new ResolveEventHandler(
742 m_AppDomains[appDomain].AssemblyResolve += 814 AssemblyResolver.OnAssemblyResolve);
743 new ResolveEventHandler( 815 m_DomainScripts[appDomain] = new List<UUID>();
744 AssemblyResolver.OnAssemblyResolve);
745 m_DomainScripts[appDomain] = new List<UUID>();
746 }
747 catch (Exception e)
748 {
749 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
750 m_ScriptErrorMessage += "Exception creating app domain:\n";
751 m_ScriptFailCount++;
752 lock (m_AddingAssemblies)
753 {
754 m_AddingAssemblies[assembly]--;
755 }
756 return false;
757 }
758 } 816 }
759 m_DomainScripts[appDomain].Add(itemID); 817 catch (Exception e)
760
761 instance = new ScriptInstance(this, part,
762 itemID, assetID, assembly,
763 m_AppDomains[appDomain],
764 part.ParentGroup.RootPart.Name,
765 item.Name, startParam, postOnRez,
766 stateSource, m_MaxScriptQueue);
767
768 m_log.DebugFormat("[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}",
769 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, part.ParentGroup.RootPart.AbsolutePosition.ToString());
770
771 if (presence != null)
772 { 818 {
773 ShowScriptSaveResponse(item.OwnerID, 819 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
774 assetID, "Compile successful", true); 820 m_ScriptErrorMessage += "Exception creating app domain:\n";
821 m_ScriptFailCount++;
822 lock (m_AddingAssemblies)
823 {
824 m_AddingAssemblies[assembly]--;
825 }
826 return false;
775 } 827 }
828 }
829 m_DomainScripts[appDomain].Add(itemID);
776 830
777 instance.AppDomain = appDomain; 831 instance = new ScriptInstance(this, part,
778 instance.LineMap = linemap; 832 itemID, assetID, assembly,
833 m_AppDomains[appDomain],
834 part.ParentGroup.RootPart.Name,
835 item.Name, startParam, postOnRez,
836 stateSource, m_MaxScriptQueue);
779 837
780 m_Scripts[itemID] = instance; 838 m_log.DebugFormat("[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}",
781 } 839 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, part.ParentGroup.RootPart.AbsolutePosition.ToString());
782 840
783 lock (m_PrimObjects) 841 if (presence != null)
784 { 842 {
785 if (!m_PrimObjects.ContainsKey(localID)) 843 ShowScriptSaveResponse(item.OwnerID,
786 m_PrimObjects[localID] = new List<UUID>(); 844 assetID, "Compile successful", true);
845 }
787 846
788 if (!m_PrimObjects[localID].Contains(itemID)) 847 instance.AppDomain = appDomain;
789 m_PrimObjects[localID].Add(itemID); 848 instance.LineMap = linemap;
849 lockScriptsForWrite(true);
850 m_Scripts[itemID] = instance;
851 lockScriptsForWrite(false);
852 }
853 else
854 {
855 lockScriptsForRead(false);
856 }
857 lock (m_PrimObjects)
858 {
859 if (!m_PrimObjects.ContainsKey(localID))
860 m_PrimObjects[localID] = new List<UUID>();
790 861
791 } 862 if (!m_PrimObjects[localID].Contains(itemID))
863 m_PrimObjects[localID].Add(itemID);
792 864
793 if (!m_Assemblies.ContainsKey(assetID)) 865 }
794 m_Assemblies[assetID] = assembly;
795 866
796 lock (m_AddingAssemblies) 867 if (!m_Assemblies.ContainsKey(assetID))
797 { 868 m_Assemblies[assetID] = assembly;
798 m_AddingAssemblies[assembly]--;
799 }
800 869
801 if (instance!=null) 870 lock (m_AddingAssemblies)
802 instance.Init(); 871 {
872 m_AddingAssemblies[assembly]--;
803 } 873 }
874
875 if (instance!=null)
876 instance.Init();
877
804 return true; 878 return true;
805 } 879 }
806 880
@@ -813,60 +887,65 @@ namespace OpenSim.Region.ScriptEngine.XEngine
813 m_CompileDict.Remove(itemID); 887 m_CompileDict.Remove(itemID);
814 } 888 }
815 889
816 lock (m_Scripts) 890 lockScriptsForRead(true);
891 // Do we even have it?
892 if (!m_Scripts.ContainsKey(itemID))
817 { 893 {
818 // Do we even have it? 894 lockScriptsForRead(false);
819 if (!m_Scripts.ContainsKey(itemID)) 895 return;
820 return; 896 }
821 897
822 IScriptInstance instance=m_Scripts[itemID];
823 m_Scripts.Remove(itemID);
824 898
825 instance.ClearQueue(); 899 IScriptInstance instance=m_Scripts[itemID];
826 instance.Stop(0); 900 lockScriptsForRead(false);
901 lockScriptsForWrite(true);
902 m_Scripts.Remove(itemID);
903 lockScriptsForWrite(false);
904 instance.ClearQueue();
905 instance.Stop(0);
827 906
828// bool objectRemoved = false; 907// bool objectRemoved = false;
829 908
830 lock (m_PrimObjects) 909 lock (m_PrimObjects)
910 {
911 // Remove the script from it's prim
912 if (m_PrimObjects.ContainsKey(localID))
831 { 913 {
832 // Remove the script from it's prim 914 // Remove inventory item record
833 if (m_PrimObjects.ContainsKey(localID)) 915 if (m_PrimObjects[localID].Contains(itemID))
834 { 916 m_PrimObjects[localID].Remove(itemID);
835 // Remove inventory item record
836 if (m_PrimObjects[localID].Contains(itemID))
837 m_PrimObjects[localID].Remove(itemID);
838 917
839 // If there are no more scripts, remove prim 918 // If there are no more scripts, remove prim
840 if (m_PrimObjects[localID].Count == 0) 919 if (m_PrimObjects[localID].Count == 0)
841 { 920 {
842 m_PrimObjects.Remove(localID); 921 m_PrimObjects.Remove(localID);
843// objectRemoved = true; 922// objectRemoved = true;
844 }
845 } 923 }
846 } 924 }
925 }
847 926
848 instance.RemoveState(); 927 instance.RemoveState();
849 instance.DestroyScriptInstance(); 928 instance.DestroyScriptInstance();
850
851 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
852 if (m_DomainScripts[instance.AppDomain].Count == 0)
853 {
854 m_DomainScripts.Remove(instance.AppDomain);
855 UnloadAppDomain(instance.AppDomain);
856 }
857 929
858 instance = null; 930 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
931 if (m_DomainScripts[instance.AppDomain].Count == 0)
932 {
933 m_DomainScripts.Remove(instance.AppDomain);
934 UnloadAppDomain(instance.AppDomain);
935 }
859 936
860 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 937 instance = null;
861 if (handlerObjectRemoved != null)
862 {
863 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
864 handlerObjectRemoved(part.UUID);
865 }
866 938
867 CleanAssemblies(); 939 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
940 if (handlerObjectRemoved != null)
941 {
942 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
943 handlerObjectRemoved(part.UUID);
868 } 944 }
869 945
946 CleanAssemblies();
947
948
870 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 949 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
871 if (handlerScriptRemoved != null) 950 if (handlerScriptRemoved != null)
872 handlerScriptRemoved(itemID); 951 handlerScriptRemoved(itemID);
@@ -1118,12 +1197,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1118 private IScriptInstance GetInstance(UUID itemID) 1197 private IScriptInstance GetInstance(UUID itemID)
1119 { 1198 {
1120 IScriptInstance instance; 1199 IScriptInstance instance;
1121 lock (m_Scripts) 1200 lockScriptsForRead(true);
1201 if (!m_Scripts.ContainsKey(itemID))
1122 { 1202 {
1123 if (!m_Scripts.ContainsKey(itemID)) 1203 lockScriptsForRead(false);
1124 return null; 1204 return null;
1125 instance = m_Scripts[itemID];
1126 } 1205 }
1206 instance = m_Scripts[itemID];
1207 lockScriptsForRead(false);
1127 return instance; 1208 return instance;
1128 } 1209 }
1129 1210
@@ -1147,6 +1228,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1147 return false; 1228 return false;
1148 } 1229 }
1149 1230
1231 [DebuggerNonUserCode]
1150 public void ApiResetScript(UUID itemID) 1232 public void ApiResetScript(UUID itemID)
1151 { 1233 {
1152 IScriptInstance instance = GetInstance(itemID); 1234 IScriptInstance instance = GetInstance(itemID);
@@ -1198,6 +1280,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1198 return UUID.Zero; 1280 return UUID.Zero;
1199 } 1281 }
1200 1282
1283 [DebuggerNonUserCode]
1201 public void SetState(UUID itemID, string newState) 1284 public void SetState(UUID itemID, string newState)
1202 { 1285 {
1203 IScriptInstance instance = GetInstance(itemID); 1286 IScriptInstance instance = GetInstance(itemID);
@@ -1218,11 +1301,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1218 { 1301 {
1219 List<IScriptInstance> instances = new List<IScriptInstance>(); 1302 List<IScriptInstance> instances = new List<IScriptInstance>();
1220 1303
1221 lock (m_Scripts) 1304 lockScriptsForRead(true);
1222 { 1305 foreach (IScriptInstance instance in m_Scripts.Values)
1223 foreach (IScriptInstance instance in m_Scripts.Values)
1224 instances.Add(instance); 1306 instances.Add(instance);
1225 } 1307 lockScriptsForRead(false);
1226 1308
1227 foreach (IScriptInstance i in instances) 1309 foreach (IScriptInstance i in instances)
1228 { 1310 {