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.cs424
1 files changed, 253 insertions, 171 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 9030a5c..184af19 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;
@@ -100,6 +101,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
100 private Dictionary<UUID, IScriptInstance> m_Scripts = 101 private Dictionary<UUID, IScriptInstance> m_Scripts =
101 new Dictionary<UUID, IScriptInstance>(); 102 new Dictionary<UUID, IScriptInstance>();
102 103
104 private OpenMetaverse.ReaderWriterLockSlim m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
105
103 // Maps the asset ID to the assembly 106 // Maps the asset ID to the assembly
104 107
105 private Dictionary<UUID, string> m_Assemblies = 108 private Dictionary<UUID, string> m_Assemblies =
@@ -121,6 +124,71 @@ namespace OpenSim.Region.ScriptEngine.XEngine
121 private ScriptCompileQueue m_CompileQueue = new ScriptCompileQueue(); 124 private ScriptCompileQueue m_CompileQueue = new ScriptCompileQueue();
122 IWorkItemResult m_CurrentCompile = null; 125 IWorkItemResult m_CurrentCompile = null;
123 126
127 private void lockScriptsForRead(bool locked)
128 {
129 if (locked)
130 {
131 if (m_scriptsLock.RecursiveReadCount > 0)
132 {
133 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.");
134 m_scriptsLock.ExitReadLock();
135 }
136 if (m_scriptsLock.RecursiveWriteCount > 0)
137 {
138 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
139 m_scriptsLock.ExitWriteLock();
140 }
141
142 while (!m_scriptsLock.TryEnterReadLock(60000))
143 {
144 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.");
145 if (m_scriptsLock.IsWriteLockHeld)
146 {
147 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
148 }
149 }
150 }
151 else
152 {
153 if (m_scriptsLock.RecursiveReadCount > 0)
154 {
155 m_scriptsLock.ExitReadLock();
156 }
157 }
158 }
159 private void lockScriptsForWrite(bool locked)
160 {
161 if (locked)
162 {
163 if (m_scriptsLock.RecursiveReadCount > 0)
164 {
165 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.");
166 m_scriptsLock.ExitReadLock();
167 }
168 if (m_scriptsLock.RecursiveWriteCount > 0)
169 {
170 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
171 m_scriptsLock.ExitWriteLock();
172 }
173
174 while (!m_scriptsLock.TryEnterWriteLock(60000))
175 {
176 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.");
177 if (m_scriptsLock.IsWriteLockHeld)
178 {
179 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
180 }
181 }
182 }
183 else
184 {
185 if (m_scriptsLock.RecursiveWriteCount > 0)
186 {
187 m_scriptsLock.ExitWriteLock();
188 }
189 }
190 }
191
124 public string ScriptEngineName 192 public string ScriptEngineName
125 { 193 {
126 get { return "XEngine"; } 194 get { return "XEngine"; }
@@ -260,43 +328,45 @@ namespace OpenSim.Region.ScriptEngine.XEngine
260 328
261 public void RemoveRegion(Scene scene) 329 public void RemoveRegion(Scene scene)
262 { 330 {
263 lock (m_Scripts) 331 lockScriptsForRead(true);
332 foreach (IScriptInstance instance in m_Scripts.Values)
264 { 333 {
265 foreach (IScriptInstance instance in m_Scripts.Values) 334 // Force a final state save
335 //
336 if (m_Assemblies.ContainsKey(instance.AssetID))
266 { 337 {
267 // Force a final state save 338 string assembly = m_Assemblies[instance.AssetID];
268 // 339 instance.SaveState(assembly);
269 if (m_Assemblies.ContainsKey(instance.AssetID)) 340 }
270 {
271 string assembly = m_Assemblies[instance.AssetID];
272 instance.SaveState(assembly);
273 }
274 341
275 // Clear the event queue and abort the instance thread 342 // Clear the event queue and abort the instance thread
276 // 343 //
277 instance.ClearQueue(); 344 instance.ClearQueue();
278 instance.Stop(0); 345 instance.Stop(0);
279 346
280 // Release events, timer, etc 347 // Release events, timer, etc
281 // 348 //
282 instance.DestroyScriptInstance(); 349 instance.DestroyScriptInstance();
283 350
284 // Unload scripts and app domains 351 // Unload scripts and app domains
285 // Must be done explicitly because they have infinite 352 // Must be done explicitly because they have infinite
286 // lifetime 353 // lifetime
287 // 354 //
288 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 355 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
289 if (m_DomainScripts[instance.AppDomain].Count == 0) 356 if (m_DomainScripts[instance.AppDomain].Count == 0)
290 { 357 {
291 m_DomainScripts.Remove(instance.AppDomain); 358 m_DomainScripts.Remove(instance.AppDomain);
292 UnloadAppDomain(instance.AppDomain); 359 UnloadAppDomain(instance.AppDomain);
293 }
294 } 360 }
295 m_Scripts.Clear();
296 m_PrimObjects.Clear();
297 m_Assemblies.Clear();
298 m_DomainScripts.Clear();
299 } 361 }
362 lockScriptsForRead(false);
363 lockScriptsForWrite(true);
364 m_Scripts.Clear();
365 lockScriptsForWrite(false);
366 m_PrimObjects.Clear();
367 m_Assemblies.Clear();
368 m_DomainScripts.Clear();
369
300 lock (m_ScriptEngines) 370 lock (m_ScriptEngines)
301 { 371 {
302 m_ScriptEngines.Remove(this); 372 m_ScriptEngines.Remove(this);
@@ -355,22 +425,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
355 425
356 List<IScriptInstance> instances = new List<IScriptInstance>(); 426 List<IScriptInstance> instances = new List<IScriptInstance>();
357 427
358 lock (m_Scripts) 428 lockScriptsForRead(true);
359 { 429 foreach (IScriptInstance instance in m_Scripts.Values)
360 foreach (IScriptInstance instance in m_Scripts.Values)
361 instances.Add(instance); 430 instances.Add(instance);
362 } 431 lockScriptsForRead(false);
363 432
364 foreach (IScriptInstance i in instances) 433 foreach (IScriptInstance i in instances)
365 { 434 {
366 string assembly = String.Empty; 435 string assembly = String.Empty;
367 436
368 lock (m_Scripts) 437
369 {
370 if (!m_Assemblies.ContainsKey(i.AssetID)) 438 if (!m_Assemblies.ContainsKey(i.AssetID))
371 continue; 439 continue;
372 assembly = m_Assemblies[i.AssetID]; 440 assembly = m_Assemblies[i.AssetID];
373 } 441
374 442
375 i.SaveState(assembly); 443 i.SaveState(assembly);
376 } 444 }
@@ -672,172 +740,183 @@ namespace OpenSim.Region.ScriptEngine.XEngine
672 return false; 740 return false;
673 } 741 }
674 742
675 lock (m_Scripts) 743
744
745 ScriptInstance instance = null;
746 // Create the object record
747 lockScriptsForRead(true);
748 if ((!m_Scripts.ContainsKey(itemID)) ||
749 (m_Scripts[itemID].AssetID != assetID))
676 { 750 {
677 ScriptInstance instance = null; 751 lockScriptsForRead(false);
678 // Create the object record
679 752
680 if ((!m_Scripts.ContainsKey(itemID)) || 753 UUID appDomain = assetID;
681 (m_Scripts[itemID].AssetID != assetID))
682 {
683 UUID appDomain = assetID;
684 754
685 if (part.ParentGroup.IsAttachment) 755 if (part.ParentGroup.IsAttachment)
686 appDomain = part.ParentGroup.RootPart.UUID; 756 appDomain = part.ParentGroup.RootPart.UUID;
687 757
688 if (!m_AppDomains.ContainsKey(appDomain)) 758 if (!m_AppDomains.ContainsKey(appDomain))
759 {
760 try
689 { 761 {
690 try 762 AppDomainSetup appSetup = new AppDomainSetup();
691 { 763 // appSetup.ApplicationBase = Path.Combine(
692 AppDomainSetup appSetup = new AppDomainSetup(); 764 // "ScriptEngines",
693// appSetup.ApplicationBase = Path.Combine( 765 // m_Scene.RegionInfo.RegionID.ToString());
694// "ScriptEngines", 766
695// m_Scene.RegionInfo.RegionID.ToString()); 767 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
696 768 Evidence evidence = new Evidence(baseEvidence);
697 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 769
698 Evidence evidence = new Evidence(baseEvidence); 770 AppDomain sandbox;
699 771 if (m_AppDomainLoading)
700 AppDomain sandbox; 772 sandbox = AppDomain.CreateDomain(
701 if (m_AppDomainLoading) 773 m_Scene.RegionInfo.RegionID.ToString(),
702 sandbox = AppDomain.CreateDomain( 774 evidence, appSetup);
703 m_Scene.RegionInfo.RegionID.ToString(), 775 else
704 evidence, appSetup); 776 sandbox = AppDomain.CurrentDomain;
705 else 777
706 sandbox = AppDomain.CurrentDomain; 778 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
707 779 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
708 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); 780 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
709 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); 781 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
710 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet"); 782 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
711 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet); 783 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
712 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement); 784 //sandbox.SetAppDomainPolicy(sandboxPolicy);
713 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup; 785
714 //sandbox.SetAppDomainPolicy(sandboxPolicy); 786 m_AppDomains[appDomain] = sandbox;
715 787
716 m_AppDomains[appDomain] = sandbox; 788 m_AppDomains[appDomain].AssemblyResolve +=
717 789 new ResolveEventHandler(
718 m_AppDomains[appDomain].AssemblyResolve += 790 AssemblyResolver.OnAssemblyResolve);
719 new ResolveEventHandler( 791 m_DomainScripts[appDomain] = new List<UUID>();
720 AssemblyResolver.OnAssemblyResolve);
721 m_DomainScripts[appDomain] = new List<UUID>();
722 }
723 catch (Exception e)
724 {
725 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
726 m_ScriptErrorMessage += "Exception creating app domain:\n";
727 m_ScriptFailCount++;
728 lock (m_AddingAssemblies)
729 {
730 m_AddingAssemblies[assembly]--;
731 }
732 return false;
733 }
734 } 792 }
735 m_DomainScripts[appDomain].Add(itemID); 793 catch (Exception e)
736
737 instance = new ScriptInstance(this, part,
738 itemID, assetID, assembly,
739 m_AppDomains[appDomain],
740 part.ParentGroup.RootPart.Name,
741 item.Name, startParam, postOnRez,
742 stateSource, m_MaxScriptQueue);
743
744 m_log.DebugFormat("[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}",
745 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, part.ParentGroup.RootPart.AbsolutePosition.ToString());
746
747 if (presence != null)
748 { 794 {
749 ShowScriptSaveResponse(item.OwnerID, 795 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
750 assetID, "Compile successful", true); 796 m_ScriptErrorMessage += "Exception creating app domain:\n";
797 m_ScriptFailCount++;
798 lock (m_AddingAssemblies)
799 {
800 m_AddingAssemblies[assembly]--;
801 }
802 return false;
751 } 803 }
804 }
805 m_DomainScripts[appDomain].Add(itemID);
752 806
753 instance.AppDomain = appDomain; 807 instance = new ScriptInstance(this, part,
754 instance.LineMap = linemap; 808 itemID, assetID, assembly,
809 m_AppDomains[appDomain],
810 part.ParentGroup.RootPart.Name,
811 item.Name, startParam, postOnRez,
812 stateSource, m_MaxScriptQueue);
755 813
756 m_Scripts[itemID] = instance; 814 m_log.DebugFormat("[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}",
757 } 815 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, part.ParentGroup.RootPart.AbsolutePosition.ToString());
758 816
759 lock (m_PrimObjects) 817 if (presence != null)
760 { 818 {
761 if (!m_PrimObjects.ContainsKey(localID)) 819 ShowScriptSaveResponse(item.OwnerID,
762 m_PrimObjects[localID] = new List<UUID>(); 820 assetID, "Compile successful", true);
821 }
763 822
764 if (!m_PrimObjects[localID].Contains(itemID)) 823 instance.AppDomain = appDomain;
765 m_PrimObjects[localID].Add(itemID); 824 instance.LineMap = linemap;
825 lockScriptsForWrite(true);
826 m_Scripts[itemID] = instance;
827 lockScriptsForWrite(false);
828 }
829 else
830 {
831 lockScriptsForRead(false);
832 }
833 lock (m_PrimObjects)
834 {
835 if (!m_PrimObjects.ContainsKey(localID))
836 m_PrimObjects[localID] = new List<UUID>();
766 837
767 } 838 if (!m_PrimObjects[localID].Contains(itemID))
839 m_PrimObjects[localID].Add(itemID);
768 840
769 if (!m_Assemblies.ContainsKey(assetID)) 841 }
770 m_Assemblies[assetID] = assembly;
771 842
772 lock (m_AddingAssemblies) 843 if (!m_Assemblies.ContainsKey(assetID))
773 { 844 m_Assemblies[assetID] = assembly;
774 m_AddingAssemblies[assembly]--;
775 }
776 845
777 if (instance!=null) 846 lock (m_AddingAssemblies)
778 instance.Init(); 847 {
848 m_AddingAssemblies[assembly]--;
779 } 849 }
850
851 if (instance!=null)
852 instance.Init();
853
780 return true; 854 return true;
781 } 855 }
782 856
783 public void OnRemoveScript(uint localID, UUID itemID) 857 public void OnRemoveScript(uint localID, UUID itemID)
784 { 858 {
785 lock (m_Scripts) 859 lockScriptsForRead(true);
860 // Do we even have it?
861 if (!m_Scripts.ContainsKey(itemID))
786 { 862 {
787 // Do we even have it? 863 lockScriptsForRead(false);
788 if (!m_Scripts.ContainsKey(itemID)) 864 return;
789 return; 865 }
790 866
791 IScriptInstance instance=m_Scripts[itemID];
792 m_Scripts.Remove(itemID);
793 867
794 instance.ClearQueue(); 868 IScriptInstance instance=m_Scripts[itemID];
795 instance.Stop(0); 869 lockScriptsForRead(false);
870 lockScriptsForWrite(true);
871 m_Scripts.Remove(itemID);
872 lockScriptsForWrite(false);
873 instance.ClearQueue();
874 instance.Stop(0);
796 875
797 SceneObjectPart part = 876 SceneObjectPart part =
798 m_Scene.GetSceneObjectPart(localID); 877 m_Scene.GetSceneObjectPart(localID);
799 878
800 if (part != null) 879 if (part != null)
801 part.RemoveScriptEvents(itemID); 880 part.RemoveScriptEvents(itemID);
802 881
803// bool objectRemoved = false; 882// bool objectRemoved = false;
804 883
805 lock (m_PrimObjects) 884 lock (m_PrimObjects)
885 {
886 // Remove the script from it's prim
887 if (m_PrimObjects.ContainsKey(localID))
806 { 888 {
807 // Remove the script from it's prim 889 // Remove inventory item record
808 if (m_PrimObjects.ContainsKey(localID)) 890 if (m_PrimObjects[localID].Contains(itemID))
809 { 891 m_PrimObjects[localID].Remove(itemID);
810 // Remove inventory item record
811 if (m_PrimObjects[localID].Contains(itemID))
812 m_PrimObjects[localID].Remove(itemID);
813 892
814 // If there are no more scripts, remove prim 893 // If there are no more scripts, remove prim
815 if (m_PrimObjects[localID].Count == 0) 894 if (m_PrimObjects[localID].Count == 0)
816 { 895 {
817 m_PrimObjects.Remove(localID); 896 m_PrimObjects.Remove(localID);
818// objectRemoved = true; 897// objectRemoved = true;
819 }
820 } 898 }
821 } 899 }
900 }
822 901
823 instance.RemoveState(); 902 instance.RemoveState();
824 instance.DestroyScriptInstance(); 903 instance.DestroyScriptInstance();
825 904
826 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 905 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
827 if (m_DomainScripts[instance.AppDomain].Count == 0) 906 if (m_DomainScripts[instance.AppDomain].Count == 0)
828 { 907 {
829 m_DomainScripts.Remove(instance.AppDomain); 908 m_DomainScripts.Remove(instance.AppDomain);
830 UnloadAppDomain(instance.AppDomain); 909 UnloadAppDomain(instance.AppDomain);
831 } 910 }
832 911
833 instance = null; 912 instance = null;
834 913
835 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 914 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
836 if (handlerObjectRemoved != null) 915 if (handlerObjectRemoved != null)
837 handlerObjectRemoved(part.UUID); 916 handlerObjectRemoved(part.UUID);
838 917
839 CleanAssemblies(); 918 CleanAssemblies();
840 } 919
841 920
842 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 921 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
843 if (handlerScriptRemoved != null) 922 if (handlerScriptRemoved != null)
@@ -1090,12 +1169,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1090 private IScriptInstance GetInstance(UUID itemID) 1169 private IScriptInstance GetInstance(UUID itemID)
1091 { 1170 {
1092 IScriptInstance instance; 1171 IScriptInstance instance;
1093 lock (m_Scripts) 1172 lockScriptsForRead(true);
1173 if (!m_Scripts.ContainsKey(itemID))
1094 { 1174 {
1095 if (!m_Scripts.ContainsKey(itemID)) 1175 lockScriptsForRead(false);
1096 return null; 1176 return null;
1097 instance = m_Scripts[itemID];
1098 } 1177 }
1178 instance = m_Scripts[itemID];
1179 lockScriptsForRead(false);
1099 return instance; 1180 return instance;
1100 } 1181 }
1101 1182
@@ -1119,6 +1200,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1119 return false; 1200 return false;
1120 } 1201 }
1121 1202
1203 [DebuggerNonUserCode]
1122 public void ApiResetScript(UUID itemID) 1204 public void ApiResetScript(UUID itemID)
1123 { 1205 {
1124 IScriptInstance instance = GetInstance(itemID); 1206 IScriptInstance instance = GetInstance(itemID);
@@ -1170,6 +1252,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1170 return UUID.Zero; 1252 return UUID.Zero;
1171 } 1253 }
1172 1254
1255 [DebuggerNonUserCode]
1173 public void SetState(UUID itemID, string newState) 1256 public void SetState(UUID itemID, string newState)
1174 { 1257 {
1175 IScriptInstance instance = GetInstance(itemID); 1258 IScriptInstance instance = GetInstance(itemID);
@@ -1197,11 +1280,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1197 { 1280 {
1198 List<IScriptInstance> instances = new List<IScriptInstance>(); 1281 List<IScriptInstance> instances = new List<IScriptInstance>();
1199 1282
1200 lock (m_Scripts) 1283 lockScriptsForRead(true);
1201 { 1284 foreach (IScriptInstance instance in m_Scripts.Values)
1202 foreach (IScriptInstance instance in m_Scripts.Values)
1203 instances.Add(instance); 1285 instances.Add(instance);
1204 } 1286 lockScriptsForRead(false);
1205 1287
1206 foreach (IScriptInstance i in instances) 1288 foreach (IScriptInstance i in instances)
1207 { 1289 {