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.cs357
1 files changed, 222 insertions, 135 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 2a0ec37..32d1fd3 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"; }
@@ -271,47 +339,45 @@ namespace OpenSim.Region.ScriptEngine.XEngine
271 { 339 {
272 if (!m_Enabled) 340 if (!m_Enabled)
273 return; 341 return;
274 342 lockScriptsForRead(true);
275 lock (m_Scripts) 343 foreach (IScriptInstance instance in m_Scripts.Values)
276 { 344 {
277 m_log.InfoFormat( 345 // Force a final state save
278 "[XEngine]: Shutting down {0} scripts in {1}", m_Scripts.Count, m_Scene.RegionInfo.RegionName); 346 //
279 347 if (m_Assemblies.ContainsKey(instance.AssetID))
280 foreach (IScriptInstance instance in m_Scripts.Values)
281 { 348 {
282 // Force a final state save 349 string assembly = m_Assemblies[instance.AssetID];
283 // 350 instance.SaveState(assembly);
284 if (m_Assemblies.ContainsKey(instance.AssetID)) 351 }
285 {
286 string assembly = m_Assemblies[instance.AssetID];
287 instance.SaveState(assembly);
288 }
289 352
290 // Clear the event queue and abort the instance thread 353 // Clear the event queue and abort the instance thread
291 // 354 //
292 instance.ClearQueue(); 355 instance.ClearQueue();
293 instance.Stop(0); 356 instance.Stop(0);
294 357
295 // Release events, timer, etc 358 // Release events, timer, etc
296 // 359 //
297 instance.DestroyScriptInstance(); 360 instance.DestroyScriptInstance();
298 361
299 // Unload scripts and app domains 362 // Unload scripts and app domains
300 // Must be done explicitly because they have infinite 363 // Must be done explicitly because they have infinite
301 // lifetime 364 // lifetime
302 // 365 //
303 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 366 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
304 if (m_DomainScripts[instance.AppDomain].Count == 0) 367 if (m_DomainScripts[instance.AppDomain].Count == 0)
305 { 368 {
306 m_DomainScripts.Remove(instance.AppDomain); 369 m_DomainScripts.Remove(instance.AppDomain);
307 UnloadAppDomain(instance.AppDomain); 370 UnloadAppDomain(instance.AppDomain);
308 }
309 } 371 }
310 m_Scripts.Clear();
311 m_PrimObjects.Clear();
312 m_Assemblies.Clear();
313 m_DomainScripts.Clear();
314 } 372 }
373 lockScriptsForRead(false);
374 lockScriptsForWrite(true);
375 m_Scripts.Clear();
376 lockScriptsForWrite(false);
377 m_PrimObjects.Clear();
378 m_Assemblies.Clear();
379 m_DomainScripts.Clear();
380
315 lock (m_ScriptEngines) 381 lock (m_ScriptEngines)
316 { 382 {
317 m_ScriptEngines.Remove(this); 383 m_ScriptEngines.Remove(this);
@@ -376,22 +442,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
376 442
377 List<IScriptInstance> instances = new List<IScriptInstance>(); 443 List<IScriptInstance> instances = new List<IScriptInstance>();
378 444
379 lock (m_Scripts) 445 lockScriptsForRead(true);
380 { 446 foreach (IScriptInstance instance in m_Scripts.Values)
381 foreach (IScriptInstance instance in m_Scripts.Values)
382 instances.Add(instance); 447 instances.Add(instance);
383 } 448 lockScriptsForRead(false);
384 449
385 foreach (IScriptInstance i in instances) 450 foreach (IScriptInstance i in instances)
386 { 451 {
387 string assembly = String.Empty; 452 string assembly = String.Empty;
388 453
389 lock (m_Scripts) 454
390 {
391 if (!m_Assemblies.ContainsKey(i.AssetID)) 455 if (!m_Assemblies.ContainsKey(i.AssetID))
392 continue; 456 continue;
393 assembly = m_Assemblies[i.AssetID]; 457 assembly = m_Assemblies[i.AssetID];
394 } 458
395 459
396 i.SaveState(assembly); 460 i.SaveState(assembly);
397 } 461 }
@@ -725,92 +789,95 @@ namespace OpenSim.Region.ScriptEngine.XEngine
725 } 789 }
726 790
727 ScriptInstance instance = null; 791 ScriptInstance instance = null;
728 lock (m_Scripts) 792 // Create the object record
793 lockScriptsForRead(true);
794 if ((!m_Scripts.ContainsKey(itemID)) ||
795 (m_Scripts[itemID].AssetID != assetID))
729 { 796 {
730 // Create the object record 797 lockScriptsForRead(false);
731 798
732 if ((!m_Scripts.ContainsKey(itemID)) || 799 UUID appDomain = assetID;
733 (m_Scripts[itemID].AssetID != assetID))
734 {
735 UUID appDomain = assetID;
736 800
737 if (part.ParentGroup.IsAttachment) 801 if (part.ParentGroup.IsAttachment)
738 appDomain = part.ParentGroup.RootPart.UUID; 802 appDomain = part.ParentGroup.RootPart.UUID;
739 803
740 if (!m_AppDomains.ContainsKey(appDomain)) 804 if (!m_AppDomains.ContainsKey(appDomain))
805 {
806 try
741 { 807 {
742 try 808 AppDomainSetup appSetup = new AppDomainSetup();
743 { 809 appSetup.PrivateBinPath = Path.Combine(
744 AppDomainSetup appSetup = new AppDomainSetup(); 810 m_ScriptEnginesPath,
745 appSetup.PrivateBinPath = Path.Combine( 811 m_Scene.RegionInfo.RegionID.ToString());
746 m_ScriptEnginesPath, 812
747 m_Scene.RegionInfo.RegionID.ToString()); 813 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
748 814 Evidence evidence = new Evidence(baseEvidence);
749 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 815
750 Evidence evidence = new Evidence(baseEvidence); 816 AppDomain sandbox;
751 817 if (m_AppDomainLoading)
752 AppDomain sandbox; 818 sandbox = AppDomain.CreateDomain(
753 if (m_AppDomainLoading) 819 m_Scene.RegionInfo.RegionID.ToString(),
754 sandbox = AppDomain.CreateDomain( 820 evidence, appSetup);
755 m_Scene.RegionInfo.RegionID.ToString(), 821 else
756 evidence, appSetup); 822 sandbox = AppDomain.CurrentDomain;
757 else 823
758 sandbox = AppDomain.CurrentDomain; 824 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
759 825 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
760 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); 826 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
761 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); 827 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
762 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet"); 828 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
763 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet); 829 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
764 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement); 830 //sandbox.SetAppDomainPolicy(sandboxPolicy);
765 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup; 831
766 //sandbox.SetAppDomainPolicy(sandboxPolicy); 832 m_AppDomains[appDomain] = sandbox;
767 833
768 m_AppDomains[appDomain] = sandbox; 834 m_AppDomains[appDomain].AssemblyResolve +=
769 835 new ResolveEventHandler(
770 m_AppDomains[appDomain].AssemblyResolve += 836 AssemblyResolver.OnAssemblyResolve);
771 new ResolveEventHandler( 837 m_DomainScripts[appDomain] = new List<UUID>();
772 AssemblyResolver.OnAssemblyResolve); 838 }
773 m_DomainScripts[appDomain] = new List<UUID>(); 839 catch (Exception e)
774 } 840 {
775 catch (Exception e) 841 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
842 m_ScriptErrorMessage += "Exception creating app domain:\n";
843 m_ScriptFailCount++;
844 lock (m_AddingAssemblies)
776 { 845 {
777 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); 846 m_AddingAssemblies[assembly]--;
778 m_ScriptErrorMessage += "Exception creating app domain:\n";
779 m_ScriptFailCount++;
780 lock (m_AddingAssemblies)
781 {
782 m_AddingAssemblies[assembly]--;
783 }
784 return false;
785 } 847 }
848 return false;
786 } 849 }
787 m_DomainScripts[appDomain].Add(itemID); 850 }
788 851 m_DomainScripts[appDomain].Add(itemID);
789 instance = new ScriptInstance(this, part, 852
790 itemID, assetID, assembly, 853 instance = new ScriptInstance(this, part,
791 m_AppDomains[appDomain], 854 itemID, assetID, assembly,
792 part.ParentGroup.RootPart.Name, 855 m_AppDomains[appDomain],
793 item.Name, startParam, postOnRez, 856 part.ParentGroup.RootPart.Name,
794 stateSource, m_MaxScriptQueue); 857 item.Name, startParam, postOnRez,
795 858 stateSource, m_MaxScriptQueue);
796 m_log.DebugFormat( 859
860 m_log.DebugFormat(
797 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}", 861 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
798 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, 862 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
799 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); 863 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
800 864
801 if (presence != null) 865 if (presence != null)
802 { 866 {
803 ShowScriptSaveResponse(item.OwnerID, 867 ShowScriptSaveResponse(item.OwnerID,
804 assetID, "Compile successful", true); 868 assetID, "Compile successful", true);
805 }
806
807 instance.AppDomain = appDomain;
808 instance.LineMap = linemap;
809
810 m_Scripts[itemID] = instance;
811 } 869 }
812 }
813 870
871 instance.AppDomain = appDomain;
872 instance.LineMap = linemap;
873 lockScriptsForWrite(true);
874 m_Scripts[itemID] = instance;
875 lockScriptsForWrite(false);
876 }
877 else
878 {
879 lockScriptsForRead(false);
880 }
814 lock (m_PrimObjects) 881 lock (m_PrimObjects)
815 { 882 {
816 if (!m_PrimObjects.ContainsKey(localID)) 883 if (!m_PrimObjects.ContainsKey(localID))
@@ -829,9 +896,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
829 m_AddingAssemblies[assembly]--; 896 m_AddingAssemblies[assembly]--;
830 } 897 }
831 898
832 if (instance != null) 899 if (instance!=null)
833 instance.Init(); 900 instance.Init();
834 901
835 return true; 902 return true;
836 } 903 }
837 904
@@ -844,20 +911,23 @@ namespace OpenSim.Region.ScriptEngine.XEngine
844 m_CompileDict.Remove(itemID); 911 m_CompileDict.Remove(itemID);
845 } 912 }
846 913
847 IScriptInstance instance = null; 914 lockScriptsForRead(true);
848 915 // Do we even have it?
849 lock (m_Scripts) 916 if (!m_Scripts.ContainsKey(itemID))
850 { 917 {
851 // Do we even have it? 918 lockScriptsForRead(false);
852 if (!m_Scripts.ContainsKey(itemID)) 919 return;
853 return;
854
855 instance=m_Scripts[itemID];
856 m_Scripts.Remove(itemID);
857 } 920 }
921
858 922
923 IScriptInstance instance=m_Scripts[itemID];
924 lockScriptsForRead(false);
925 lockScriptsForWrite(true);
926 m_Scripts.Remove(itemID);
927 lockScriptsForWrite(false);
859 instance.ClearQueue(); 928 instance.ClearQueue();
860 instance.Stop(0); 929 instance.Stop(0);
930
861// bool objectRemoved = false; 931// bool objectRemoved = false;
862 932
863 lock (m_PrimObjects) 933 lock (m_PrimObjects)
@@ -893,11 +963,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
893 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 963 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
894 if (handlerObjectRemoved != null) 964 if (handlerObjectRemoved != null)
895 { 965 {
896 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID); 966 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
897 handlerObjectRemoved(part.UUID); 967 handlerObjectRemoved(part.UUID);
898 } 968 }
899 969
900 970 CleanAssemblies();
971
901 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 972 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
902 if (handlerScriptRemoved != null) 973 if (handlerScriptRemoved != null)
903 handlerScriptRemoved(itemID); 974 handlerScriptRemoved(itemID);
@@ -1039,7 +1110,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1039 return false; 1110 return false;
1040 1111
1041 uuids = m_PrimObjects[localID]; 1112 uuids = m_PrimObjects[localID];
1042 } 1113
1043 1114
1044 foreach (UUID itemID in uuids) 1115 foreach (UUID itemID in uuids)
1045 { 1116 {
@@ -1057,6 +1128,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1057 result = true; 1128 result = true;
1058 } 1129 }
1059 } 1130 }
1131 }
1060 1132
1061 return result; 1133 return result;
1062 } 1134 }
@@ -1156,12 +1228,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1156 private IScriptInstance GetInstance(UUID itemID) 1228 private IScriptInstance GetInstance(UUID itemID)
1157 { 1229 {
1158 IScriptInstance instance; 1230 IScriptInstance instance;
1159 lock (m_Scripts) 1231 lockScriptsForRead(true);
1232 if (!m_Scripts.ContainsKey(itemID))
1160 { 1233 {
1161 if (!m_Scripts.ContainsKey(itemID)) 1234 lockScriptsForRead(false);
1162 return null; 1235 return null;
1163 instance = m_Scripts[itemID];
1164 } 1236 }
1237 instance = m_Scripts[itemID];
1238 lockScriptsForRead(false);
1165 return instance; 1239 return instance;
1166 } 1240 }
1167 1241
@@ -1185,6 +1259,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1185 return false; 1259 return false;
1186 } 1260 }
1187 1261
1262 [DebuggerNonUserCode]
1188 public void ApiResetScript(UUID itemID) 1263 public void ApiResetScript(UUID itemID)
1189 { 1264 {
1190 IScriptInstance instance = GetInstance(itemID); 1265 IScriptInstance instance = GetInstance(itemID);
@@ -1236,6 +1311,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1236 return UUID.Zero; 1311 return UUID.Zero;
1237 } 1312 }
1238 1313
1314 [DebuggerNonUserCode]
1239 public void SetState(UUID itemID, string newState) 1315 public void SetState(UUID itemID, string newState)
1240 { 1316 {
1241 IScriptInstance instance = GetInstance(itemID); 1317 IScriptInstance instance = GetInstance(itemID);
@@ -1256,11 +1332,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1256 { 1332 {
1257 List<IScriptInstance> instances = new List<IScriptInstance>(); 1333 List<IScriptInstance> instances = new List<IScriptInstance>();
1258 1334
1259 lock (m_Scripts) 1335 lockScriptsForRead(true);
1260 { 1336 foreach (IScriptInstance instance in m_Scripts.Values)
1261 foreach (IScriptInstance instance in m_Scripts.Values)
1262 instances.Add(instance); 1337 instances.Add(instance);
1263 } 1338 lockScriptsForRead(false);
1264 1339
1265 foreach (IScriptInstance i in instances) 1340 foreach (IScriptInstance i in instances)
1266 { 1341 {
@@ -1641,5 +1716,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1641 1716
1642 instance.Resume(); 1717 instance.Resume();
1643 } 1718 }
1719
1720 public bool HasScript(UUID itemID, out bool running)
1721 {
1722 running = true;
1723
1724 IScriptInstance instance = GetInstance(itemID);
1725 if (instance == null)
1726 return false;
1727
1728 running = instance.Running;
1729 return true;
1730 }
1644 } 1731 }
1645} 1732}