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.cs366
1 files changed, 231 insertions, 135 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 97ab411..4f3432d 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);
@@ -364,22 +434,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
364 434
365 List<IScriptInstance> instances = new List<IScriptInstance>(); 435 List<IScriptInstance> instances = new List<IScriptInstance>();
366 436
367 lock (m_Scripts) 437 lockScriptsForRead(true);
368 { 438 foreach (IScriptInstance instance in m_Scripts.Values)
369 foreach (IScriptInstance instance in m_Scripts.Values)
370 instances.Add(instance); 439 instances.Add(instance);
371 } 440 lockScriptsForRead(false);
372 441
373 foreach (IScriptInstance i in instances) 442 foreach (IScriptInstance i in instances)
374 { 443 {
375 string assembly = String.Empty; 444 string assembly = String.Empty;
376 445
377 lock (m_Scripts) 446
378 {
379 if (!m_Assemblies.ContainsKey(i.AssetID)) 447 if (!m_Assemblies.ContainsKey(i.AssetID))
380 continue; 448 continue;
381 assembly = m_Assemblies[i.AssetID]; 449 assembly = m_Assemblies[i.AssetID];
382 } 450
383 451
384 i.SaveState(assembly); 452 i.SaveState(assembly);
385 } 453 }
@@ -393,11 +461,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
393 return 0; 461 return 0;
394 } 462 }
395 463
396 public object DoMaintenance(object p) 464 public void SaveAllState()
397 { 465 {
398 object[] parms = (object[])p;
399 int sleepTime = (int)parms[0];
400
401 foreach (IScriptInstance inst in m_Scripts.Values) 466 foreach (IScriptInstance inst in m_Scripts.Values)
402 { 467 {
403 if (inst.EventTime() > m_EventLimit) 468 if (inst.EventTime() > m_EventLimit)
@@ -407,6 +472,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
407 inst.Start(); 472 inst.Start();
408 } 473 }
409 } 474 }
475 }
476
477 public object DoMaintenance(object p)
478 {
479 object[] parms = (object[])p;
480 int sleepTime = (int)parms[0];
481
482 SaveAllState();
410 483
411 System.Threading.Thread.Sleep(sleepTime); 484 System.Threading.Thread.Sleep(sleepTime);
412 485
@@ -708,92 +781,95 @@ namespace OpenSim.Region.ScriptEngine.XEngine
708 } 781 }
709 782
710 ScriptInstance instance = null; 783 ScriptInstance instance = null;
711 lock (m_Scripts) 784 // Create the object record
785 lockScriptsForRead(true);
786 if ((!m_Scripts.ContainsKey(itemID)) ||
787 (m_Scripts[itemID].AssetID != assetID))
712 { 788 {
713 // Create the object record 789 lockScriptsForRead(false);
714 790
715 if ((!m_Scripts.ContainsKey(itemID)) || 791 UUID appDomain = assetID;
716 (m_Scripts[itemID].AssetID != assetID))
717 {
718 UUID appDomain = assetID;
719 792
720 if (part.ParentGroup.IsAttachment) 793 if (part.ParentGroup.IsAttachment)
721 appDomain = part.ParentGroup.RootPart.UUID; 794 appDomain = part.ParentGroup.RootPart.UUID;
722 795
723 if (!m_AppDomains.ContainsKey(appDomain)) 796 if (!m_AppDomains.ContainsKey(appDomain))
797 {
798 try
724 { 799 {
725 try 800 AppDomainSetup appSetup = new AppDomainSetup();
726 { 801 appSetup.PrivateBinPath = Path.Combine(
727 AppDomainSetup appSetup = new AppDomainSetup(); 802 m_ScriptEnginesPath,
728 appSetup.PrivateBinPath = Path.Combine( 803 m_Scene.RegionInfo.RegionID.ToString());
729 m_ScriptEnginesPath, 804
730 m_Scene.RegionInfo.RegionID.ToString()); 805 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
731 806 Evidence evidence = new Evidence(baseEvidence);
732 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 807
733 Evidence evidence = new Evidence(baseEvidence); 808 AppDomain sandbox;
734 809 if (m_AppDomainLoading)
735 AppDomain sandbox; 810 sandbox = AppDomain.CreateDomain(
736 if (m_AppDomainLoading) 811 m_Scene.RegionInfo.RegionID.ToString(),
737 sandbox = AppDomain.CreateDomain( 812 evidence, appSetup);
738 m_Scene.RegionInfo.RegionID.ToString(), 813 else
739 evidence, appSetup); 814 sandbox = AppDomain.CurrentDomain;
740 else 815
741 sandbox = AppDomain.CurrentDomain; 816 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
742 817 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
743 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); 818 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
744 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); 819 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
745 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet"); 820 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
746 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet); 821 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
747 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement); 822 //sandbox.SetAppDomainPolicy(sandboxPolicy);
748 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup; 823
749 //sandbox.SetAppDomainPolicy(sandboxPolicy); 824 m_AppDomains[appDomain] = sandbox;
750 825
751 m_AppDomains[appDomain] = sandbox; 826 m_AppDomains[appDomain].AssemblyResolve +=
752 827 new ResolveEventHandler(
753 m_AppDomains[appDomain].AssemblyResolve += 828 AssemblyResolver.OnAssemblyResolve);
754 new ResolveEventHandler( 829 m_DomainScripts[appDomain] = new List<UUID>();
755 AssemblyResolver.OnAssemblyResolve); 830 }
756 m_DomainScripts[appDomain] = new List<UUID>(); 831 catch (Exception e)
757 } 832 {
758 catch (Exception e) 833 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
834 m_ScriptErrorMessage += "Exception creating app domain:\n";
835 m_ScriptFailCount++;
836 lock (m_AddingAssemblies)
759 { 837 {
760 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); 838 m_AddingAssemblies[assembly]--;
761 m_ScriptErrorMessage += "Exception creating app domain:\n";
762 m_ScriptFailCount++;
763 lock (m_AddingAssemblies)
764 {
765 m_AddingAssemblies[assembly]--;
766 }
767 return false;
768 } 839 }
840 return false;
769 } 841 }
770 m_DomainScripts[appDomain].Add(itemID); 842 }
771 843 m_DomainScripts[appDomain].Add(itemID);
772 instance = new ScriptInstance(this, part, 844
773 itemID, assetID, assembly, 845 instance = new ScriptInstance(this, part,
774 m_AppDomains[appDomain], 846 itemID, assetID, assembly,
775 part.ParentGroup.RootPart.Name, 847 m_AppDomains[appDomain],
776 item.Name, startParam, postOnRez, 848 part.ParentGroup.RootPart.Name,
777 stateSource, m_MaxScriptQueue); 849 item.Name, startParam, postOnRez,
778 850 stateSource, m_MaxScriptQueue);
779 m_log.DebugFormat( 851
852 m_log.DebugFormat(
780 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}", 853 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
781 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, 854 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
782 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); 855 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
783 856
784 if (presence != null) 857 if (presence != null)
785 { 858 {
786 ShowScriptSaveResponse(item.OwnerID, 859 ShowScriptSaveResponse(item.OwnerID,
787 assetID, "Compile successful", true); 860 assetID, "Compile successful", true);
788 }
789
790 instance.AppDomain = appDomain;
791 instance.LineMap = linemap;
792
793 m_Scripts[itemID] = instance;
794 } 861 }
795 }
796 862
863 instance.AppDomain = appDomain;
864 instance.LineMap = linemap;
865 lockScriptsForWrite(true);
866 m_Scripts[itemID] = instance;
867 lockScriptsForWrite(false);
868 }
869 else
870 {
871 lockScriptsForRead(false);
872 }
797 lock (m_PrimObjects) 873 lock (m_PrimObjects)
798 { 874 {
799 if (!m_PrimObjects.ContainsKey(localID)) 875 if (!m_PrimObjects.ContainsKey(localID))
@@ -812,9 +888,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
812 m_AddingAssemblies[assembly]--; 888 m_AddingAssemblies[assembly]--;
813 } 889 }
814 890
815 if (instance != null) 891 if (instance!=null)
816 instance.Init(); 892 instance.Init();
817 893
818 return true; 894 return true;
819 } 895 }
820 896
@@ -827,20 +903,23 @@ namespace OpenSim.Region.ScriptEngine.XEngine
827 m_CompileDict.Remove(itemID); 903 m_CompileDict.Remove(itemID);
828 } 904 }
829 905
830 IScriptInstance instance = null; 906 lockScriptsForRead(true);
831 907 // Do we even have it?
832 lock (m_Scripts) 908 if (!m_Scripts.ContainsKey(itemID))
833 { 909 {
834 // Do we even have it? 910 lockScriptsForRead(false);
835 if (!m_Scripts.ContainsKey(itemID)) 911 return;
836 return;
837
838 instance=m_Scripts[itemID];
839 m_Scripts.Remove(itemID);
840 } 912 }
913
841 914
915 IScriptInstance instance=m_Scripts[itemID];
916 lockScriptsForRead(false);
917 lockScriptsForWrite(true);
918 m_Scripts.Remove(itemID);
919 lockScriptsForWrite(false);
842 instance.ClearQueue(); 920 instance.ClearQueue();
843 instance.Stop(0); 921 instance.Stop(0);
922
844// bool objectRemoved = false; 923// bool objectRemoved = false;
845 924
846 lock (m_PrimObjects) 925 lock (m_PrimObjects)
@@ -876,11 +955,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
876 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 955 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
877 if (handlerObjectRemoved != null) 956 if (handlerObjectRemoved != null)
878 { 957 {
879 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID); 958 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
880 handlerObjectRemoved(part.UUID); 959 handlerObjectRemoved(part.UUID);
881 } 960 }
882 961
883 962 CleanAssemblies();
963
884 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 964 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
885 if (handlerScriptRemoved != null) 965 if (handlerScriptRemoved != null)
886 handlerScriptRemoved(itemID); 966 handlerScriptRemoved(itemID);
@@ -1022,7 +1102,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1022 return false; 1102 return false;
1023 1103
1024 uuids = m_PrimObjects[localID]; 1104 uuids = m_PrimObjects[localID];
1025 } 1105
1026 1106
1027 foreach (UUID itemID in uuids) 1107 foreach (UUID itemID in uuids)
1028 { 1108 {
@@ -1040,6 +1120,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1040 result = true; 1120 result = true;
1041 } 1121 }
1042 } 1122 }
1123 }
1043 1124
1044 return result; 1125 return result;
1045 } 1126 }
@@ -1139,12 +1220,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1139 private IScriptInstance GetInstance(UUID itemID) 1220 private IScriptInstance GetInstance(UUID itemID)
1140 { 1221 {
1141 IScriptInstance instance; 1222 IScriptInstance instance;
1142 lock (m_Scripts) 1223 lockScriptsForRead(true);
1224 if (!m_Scripts.ContainsKey(itemID))
1143 { 1225 {
1144 if (!m_Scripts.ContainsKey(itemID)) 1226 lockScriptsForRead(false);
1145 return null; 1227 return null;
1146 instance = m_Scripts[itemID];
1147 } 1228 }
1229 instance = m_Scripts[itemID];
1230 lockScriptsForRead(false);
1148 return instance; 1231 return instance;
1149 } 1232 }
1150 1233
@@ -1168,6 +1251,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1168 return false; 1251 return false;
1169 } 1252 }
1170 1253
1254 [DebuggerNonUserCode]
1171 public void ApiResetScript(UUID itemID) 1255 public void ApiResetScript(UUID itemID)
1172 { 1256 {
1173 IScriptInstance instance = GetInstance(itemID); 1257 IScriptInstance instance = GetInstance(itemID);
@@ -1219,6 +1303,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1219 return UUID.Zero; 1303 return UUID.Zero;
1220 } 1304 }
1221 1305
1306 [DebuggerNonUserCode]
1222 public void SetState(UUID itemID, string newState) 1307 public void SetState(UUID itemID, string newState)
1223 { 1308 {
1224 IScriptInstance instance = GetInstance(itemID); 1309 IScriptInstance instance = GetInstance(itemID);
@@ -1239,11 +1324,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1239 { 1324 {
1240 List<IScriptInstance> instances = new List<IScriptInstance>(); 1325 List<IScriptInstance> instances = new List<IScriptInstance>();
1241 1326
1242 lock (m_Scripts) 1327 lockScriptsForRead(true);
1243 { 1328 foreach (IScriptInstance instance in m_Scripts.Values)
1244 foreach (IScriptInstance instance in m_Scripts.Values)
1245 instances.Add(instance); 1329 instances.Add(instance);
1246 } 1330 lockScriptsForRead(false);
1247 1331
1248 foreach (IScriptInstance i in instances) 1332 foreach (IScriptInstance i in instances)
1249 { 1333 {
@@ -1615,5 +1699,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1615 1699
1616 instance.Resume(); 1700 instance.Resume();
1617 } 1701 }
1702
1703 public bool HasScript(UUID itemID, out bool running)
1704 {
1705 running = true;
1706
1707 IScriptInstance instance = GetInstance(itemID);
1708 if (instance == null)
1709 return false;
1710
1711 running = instance.Running;
1712 return true;
1713 }
1618 } 1714 }
1619} 1715}