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.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 9f8ee1c..572ca07 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;
@@ -103,6 +104,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
103 private Dictionary<UUID, IScriptInstance> m_Scripts = 104 private Dictionary<UUID, IScriptInstance> m_Scripts =
104 new Dictionary<UUID, IScriptInstance>(); 105 new Dictionary<UUID, IScriptInstance>();
105 106
107 private OpenMetaverse.ReaderWriterLockSlim m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
108
106 // Maps the asset ID to the assembly 109 // Maps the asset ID to the assembly
107 110
108 private Dictionary<UUID, string> m_Assemblies = 111 private Dictionary<UUID, string> m_Assemblies =
@@ -125,6 +128,71 @@ namespace OpenSim.Region.ScriptEngine.XEngine
125 IWorkItemResult m_CurrentCompile = null; 128 IWorkItemResult m_CurrentCompile = null;
126 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>(); 129 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>();
127 130
131 private void lockScriptsForRead(bool locked)
132 {
133 if (locked)
134 {
135 if (m_scriptsLock.RecursiveReadCount > 0)
136 {
137 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.");
138 m_scriptsLock.ExitReadLock();
139 }
140 if (m_scriptsLock.RecursiveWriteCount > 0)
141 {
142 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
143 m_scriptsLock.ExitWriteLock();
144 }
145
146 while (!m_scriptsLock.TryEnterReadLock(60000))
147 {
148 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.");
149 if (m_scriptsLock.IsWriteLockHeld)
150 {
151 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
152 }
153 }
154 }
155 else
156 {
157 if (m_scriptsLock.RecursiveReadCount > 0)
158 {
159 m_scriptsLock.ExitReadLock();
160 }
161 }
162 }
163 private void lockScriptsForWrite(bool locked)
164 {
165 if (locked)
166 {
167 if (m_scriptsLock.RecursiveReadCount > 0)
168 {
169 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.");
170 m_scriptsLock.ExitReadLock();
171 }
172 if (m_scriptsLock.RecursiveWriteCount > 0)
173 {
174 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
175 m_scriptsLock.ExitWriteLock();
176 }
177
178 while (!m_scriptsLock.TryEnterWriteLock(60000))
179 {
180 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.");
181 if (m_scriptsLock.IsWriteLockHeld)
182 {
183 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
184 }
185 }
186 }
187 else
188 {
189 if (m_scriptsLock.RecursiveWriteCount > 0)
190 {
191 m_scriptsLock.ExitWriteLock();
192 }
193 }
194 }
195
128 public string ScriptEngineName 196 public string ScriptEngineName
129 { 197 {
130 get { return "XEngine"; } 198 get { return "XEngine"; }
@@ -299,47 +367,45 @@ namespace OpenSim.Region.ScriptEngine.XEngine
299 { 367 {
300 if (!m_Enabled) 368 if (!m_Enabled)
301 return; 369 return;
302 370 lockScriptsForRead(true);
303 lock (m_Scripts) 371 foreach (IScriptInstance instance in m_Scripts.Values)
304 { 372 {
305 m_log.InfoFormat( 373 // Force a final state save
306 "[XEngine]: Shutting down {0} scripts in {1}", m_Scripts.Count, m_Scene.RegionInfo.RegionName); 374 //
307 375 if (m_Assemblies.ContainsKey(instance.AssetID))
308 foreach (IScriptInstance instance in m_Scripts.Values)
309 { 376 {
310 // Force a final state save 377 string assembly = m_Assemblies[instance.AssetID];
311 // 378 instance.SaveState(assembly);
312 if (m_Assemblies.ContainsKey(instance.AssetID)) 379 }
313 {
314 string assembly = m_Assemblies[instance.AssetID];
315 instance.SaveState(assembly);
316 }
317 380
318 // Clear the event queue and abort the instance thread 381 // Clear the event queue and abort the instance thread
319 // 382 //
320 instance.ClearQueue(); 383 instance.ClearQueue();
321 instance.Stop(0); 384 instance.Stop(0);
322 385
323 // Release events, timer, etc 386 // Release events, timer, etc
324 // 387 //
325 instance.DestroyScriptInstance(); 388 instance.DestroyScriptInstance();
326 389
327 // Unload scripts and app domains 390 // Unload scripts and app domains
328 // Must be done explicitly because they have infinite 391 // Must be done explicitly because they have infinite
329 // lifetime 392 // lifetime
330 // 393 //
331 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 394 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
332 if (m_DomainScripts[instance.AppDomain].Count == 0) 395 if (m_DomainScripts[instance.AppDomain].Count == 0)
333 { 396 {
334 m_DomainScripts.Remove(instance.AppDomain); 397 m_DomainScripts.Remove(instance.AppDomain);
335 UnloadAppDomain(instance.AppDomain); 398 UnloadAppDomain(instance.AppDomain);
336 }
337 } 399 }
338 m_Scripts.Clear();
339 m_PrimObjects.Clear();
340 m_Assemblies.Clear();
341 m_DomainScripts.Clear();
342 } 400 }
401 lockScriptsForRead(false);
402 lockScriptsForWrite(true);
403 m_Scripts.Clear();
404 lockScriptsForWrite(false);
405 m_PrimObjects.Clear();
406 m_Assemblies.Clear();
407 m_DomainScripts.Clear();
408
343 lock (m_ScriptEngines) 409 lock (m_ScriptEngines)
344 { 410 {
345 m_ScriptEngines.Remove(this); 411 m_ScriptEngines.Remove(this);
@@ -404,22 +470,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
404 470
405 List<IScriptInstance> instances = new List<IScriptInstance>(); 471 List<IScriptInstance> instances = new List<IScriptInstance>();
406 472
407 lock (m_Scripts) 473 lockScriptsForRead(true);
408 { 474 foreach (IScriptInstance instance in m_Scripts.Values)
409 foreach (IScriptInstance instance in m_Scripts.Values)
410 instances.Add(instance); 475 instances.Add(instance);
411 } 476 lockScriptsForRead(false);
412 477
413 foreach (IScriptInstance i in instances) 478 foreach (IScriptInstance i in instances)
414 { 479 {
415 string assembly = String.Empty; 480 string assembly = String.Empty;
416 481
417 lock (m_Scripts) 482
418 {
419 if (!m_Assemblies.ContainsKey(i.AssetID)) 483 if (!m_Assemblies.ContainsKey(i.AssetID))
420 continue; 484 continue;
421 assembly = m_Assemblies[i.AssetID]; 485 assembly = m_Assemblies[i.AssetID];
422 } 486
423 487
424 i.SaveState(assembly); 488 i.SaveState(assembly);
425 } 489 }
@@ -753,92 +817,95 @@ namespace OpenSim.Region.ScriptEngine.XEngine
753 } 817 }
754 818
755 ScriptInstance instance = null; 819 ScriptInstance instance = null;
756 lock (m_Scripts) 820 // Create the object record
821 lockScriptsForRead(true);
822 if ((!m_Scripts.ContainsKey(itemID)) ||
823 (m_Scripts[itemID].AssetID != assetID))
757 { 824 {
758 // Create the object record 825 lockScriptsForRead(false);
759 826
760 if ((!m_Scripts.ContainsKey(itemID)) || 827 UUID appDomain = assetID;
761 (m_Scripts[itemID].AssetID != assetID))
762 {
763 UUID appDomain = assetID;
764 828
765 if (part.ParentGroup.IsAttachment) 829 if (part.ParentGroup.IsAttachment)
766 appDomain = part.ParentGroup.RootPart.UUID; 830 appDomain = part.ParentGroup.RootPart.UUID;
767 831
768 if (!m_AppDomains.ContainsKey(appDomain)) 832 if (!m_AppDomains.ContainsKey(appDomain))
833 {
834 try
769 { 835 {
770 try 836 AppDomainSetup appSetup = new AppDomainSetup();
771 { 837 appSetup.PrivateBinPath = Path.Combine(
772 AppDomainSetup appSetup = new AppDomainSetup(); 838 m_ScriptEnginesPath,
773 appSetup.PrivateBinPath = Path.Combine( 839 m_Scene.RegionInfo.RegionID.ToString());
774 m_ScriptEnginesPath, 840
775 m_Scene.RegionInfo.RegionID.ToString()); 841 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
776 842 Evidence evidence = new Evidence(baseEvidence);
777 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 843
778 Evidence evidence = new Evidence(baseEvidence); 844 AppDomain sandbox;
779 845 if (m_AppDomainLoading)
780 AppDomain sandbox; 846 sandbox = AppDomain.CreateDomain(
781 if (m_AppDomainLoading) 847 m_Scene.RegionInfo.RegionID.ToString(),
782 sandbox = AppDomain.CreateDomain( 848 evidence, appSetup);
783 m_Scene.RegionInfo.RegionID.ToString(), 849 else
784 evidence, appSetup); 850 sandbox = AppDomain.CurrentDomain;
785 else 851
786 sandbox = AppDomain.CurrentDomain; 852 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
787 853 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
788 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); 854 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
789 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); 855 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
790 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet"); 856 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
791 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet); 857 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
792 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement); 858 //sandbox.SetAppDomainPolicy(sandboxPolicy);
793 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup; 859
794 //sandbox.SetAppDomainPolicy(sandboxPolicy); 860 m_AppDomains[appDomain] = sandbox;
795 861
796 m_AppDomains[appDomain] = sandbox; 862 m_AppDomains[appDomain].AssemblyResolve +=
797 863 new ResolveEventHandler(
798 m_AppDomains[appDomain].AssemblyResolve += 864 AssemblyResolver.OnAssemblyResolve);
799 new ResolveEventHandler( 865 m_DomainScripts[appDomain] = new List<UUID>();
800 AssemblyResolver.OnAssemblyResolve); 866 }
801 m_DomainScripts[appDomain] = new List<UUID>(); 867 catch (Exception e)
802 } 868 {
803 catch (Exception e) 869 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
870 m_ScriptErrorMessage += "Exception creating app domain:\n";
871 m_ScriptFailCount++;
872 lock (m_AddingAssemblies)
804 { 873 {
805 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); 874 m_AddingAssemblies[assembly]--;
806 m_ScriptErrorMessage += "Exception creating app domain:\n";
807 m_ScriptFailCount++;
808 lock (m_AddingAssemblies)
809 {
810 m_AddingAssemblies[assembly]--;
811 }
812 return false;
813 } 875 }
876 return false;
814 } 877 }
815 m_DomainScripts[appDomain].Add(itemID); 878 }
816 879 m_DomainScripts[appDomain].Add(itemID);
817 instance = new ScriptInstance(this, part, 880
818 itemID, assetID, assembly, 881 instance = new ScriptInstance(this, part,
819 m_AppDomains[appDomain], 882 itemID, assetID, assembly,
820 part.ParentGroup.RootPart.Name, 883 m_AppDomains[appDomain],
821 item.Name, startParam, postOnRez, 884 part.ParentGroup.RootPart.Name,
822 stateSource, m_MaxScriptQueue); 885 item.Name, startParam, postOnRez,
823 886 stateSource, m_MaxScriptQueue);
824 m_log.DebugFormat( 887
888 m_log.DebugFormat(
825 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}", 889 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
826 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, 890 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
827 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); 891 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
828 892
829 if (presence != null) 893 if (presence != null)
830 { 894 {
831 ShowScriptSaveResponse(item.OwnerID, 895 ShowScriptSaveResponse(item.OwnerID,
832 assetID, "Compile successful", true); 896 assetID, "Compile successful", true);
833 }
834
835 instance.AppDomain = appDomain;
836 instance.LineMap = linemap;
837
838 m_Scripts[itemID] = instance;
839 } 897 }
840 }
841 898
899 instance.AppDomain = appDomain;
900 instance.LineMap = linemap;
901 lockScriptsForWrite(true);
902 m_Scripts[itemID] = instance;
903 lockScriptsForWrite(false);
904 }
905 else
906 {
907 lockScriptsForRead(false);
908 }
842 lock (m_PrimObjects) 909 lock (m_PrimObjects)
843 { 910 {
844 if (!m_PrimObjects.ContainsKey(localID)) 911 if (!m_PrimObjects.ContainsKey(localID))
@@ -857,9 +924,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
857 m_AddingAssemblies[assembly]--; 924 m_AddingAssemblies[assembly]--;
858 } 925 }
859 926
860 if (instance != null) 927 if (instance!=null)
861 instance.Init(); 928 instance.Init();
862 929
863 return true; 930 return true;
864 } 931 }
865 932
@@ -872,20 +939,23 @@ namespace OpenSim.Region.ScriptEngine.XEngine
872 m_CompileDict.Remove(itemID); 939 m_CompileDict.Remove(itemID);
873 } 940 }
874 941
875 IScriptInstance instance = null; 942 lockScriptsForRead(true);
876 943 // Do we even have it?
877 lock (m_Scripts) 944 if (!m_Scripts.ContainsKey(itemID))
878 { 945 {
879 // Do we even have it? 946 lockScriptsForRead(false);
880 if (!m_Scripts.ContainsKey(itemID)) 947 return;
881 return;
882
883 instance=m_Scripts[itemID];
884 m_Scripts.Remove(itemID);
885 } 948 }
949
886 950
951 IScriptInstance instance=m_Scripts[itemID];
952 lockScriptsForRead(false);
953 lockScriptsForWrite(true);
954 m_Scripts.Remove(itemID);
955 lockScriptsForWrite(false);
887 instance.ClearQueue(); 956 instance.ClearQueue();
888 instance.Stop(0); 957 instance.Stop(0);
958
889// bool objectRemoved = false; 959// bool objectRemoved = false;
890 960
891 lock (m_PrimObjects) 961 lock (m_PrimObjects)
@@ -921,11 +991,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
921 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 991 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
922 if (handlerObjectRemoved != null) 992 if (handlerObjectRemoved != null)
923 { 993 {
924 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID); 994 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
925 handlerObjectRemoved(part.UUID); 995 handlerObjectRemoved(part.UUID);
926 } 996 }
927 997
928 998 CleanAssemblies();
999
929 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 1000 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
930 if (handlerScriptRemoved != null) 1001 if (handlerScriptRemoved != null)
931 handlerScriptRemoved(itemID); 1002 handlerScriptRemoved(itemID);
@@ -1067,7 +1138,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1067 return false; 1138 return false;
1068 1139
1069 uuids = m_PrimObjects[localID]; 1140 uuids = m_PrimObjects[localID];
1070 } 1141
1071 1142
1072 foreach (UUID itemID in uuids) 1143 foreach (UUID itemID in uuids)
1073 { 1144 {
@@ -1085,6 +1156,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1085 result = true; 1156 result = true;
1086 } 1157 }
1087 } 1158 }
1159 }
1088 1160
1089 return result; 1161 return result;
1090 } 1162 }
@@ -1184,12 +1256,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1184 private IScriptInstance GetInstance(UUID itemID) 1256 private IScriptInstance GetInstance(UUID itemID)
1185 { 1257 {
1186 IScriptInstance instance; 1258 IScriptInstance instance;
1187 lock (m_Scripts) 1259 lockScriptsForRead(true);
1260 if (!m_Scripts.ContainsKey(itemID))
1188 { 1261 {
1189 if (!m_Scripts.ContainsKey(itemID)) 1262 lockScriptsForRead(false);
1190 return null; 1263 return null;
1191 instance = m_Scripts[itemID];
1192 } 1264 }
1265 instance = m_Scripts[itemID];
1266 lockScriptsForRead(false);
1193 return instance; 1267 return instance;
1194 } 1268 }
1195 1269
@@ -1213,6 +1287,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1213 return false; 1287 return false;
1214 } 1288 }
1215 1289
1290 [DebuggerNonUserCode]
1216 public void ApiResetScript(UUID itemID) 1291 public void ApiResetScript(UUID itemID)
1217 { 1292 {
1218 IScriptInstance instance = GetInstance(itemID); 1293 IScriptInstance instance = GetInstance(itemID);
@@ -1264,6 +1339,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1264 return UUID.Zero; 1339 return UUID.Zero;
1265 } 1340 }
1266 1341
1342 [DebuggerNonUserCode]
1267 public void SetState(UUID itemID, string newState) 1343 public void SetState(UUID itemID, string newState)
1268 { 1344 {
1269 IScriptInstance instance = GetInstance(itemID); 1345 IScriptInstance instance = GetInstance(itemID);
@@ -1284,11 +1360,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1284 { 1360 {
1285 List<IScriptInstance> instances = new List<IScriptInstance>(); 1361 List<IScriptInstance> instances = new List<IScriptInstance>();
1286 1362
1287 lock (m_Scripts) 1363 lockScriptsForRead(true);
1288 { 1364 foreach (IScriptInstance instance in m_Scripts.Values)
1289 foreach (IScriptInstance instance in m_Scripts.Values)
1290 instances.Add(instance); 1365 instances.Add(instance);
1291 } 1366 lockScriptsForRead(false);
1292 1367
1293 foreach (IScriptInstance i in instances) 1368 foreach (IScriptInstance i in instances)
1294 { 1369 {
@@ -1669,5 +1744,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1669 1744
1670 instance.Resume(); 1745 instance.Resume();
1671 } 1746 }
1747
1748 public bool HasScript(UUID itemID, out bool running)
1749 {
1750 running = true;
1751
1752 IScriptInstance instance = GetInstance(itemID);
1753 if (instance == null)
1754 return false;
1755
1756 running = instance.Running;
1757 return true;
1758 }
1672 } 1759 }
1673} 1760}