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.cs361
1 files changed, 230 insertions, 131 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index b433430..db6a407 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Diagnostics; //for [DebuggerNonUserCode]
31using System.Globalization; 32using System.Globalization;
32using System.IO; 33using System.IO;
33using System.Reflection; 34using System.Reflection;
@@ -112,6 +113,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
112 private Dictionary<UUID, IScriptInstance> m_Scripts = 113 private Dictionary<UUID, IScriptInstance> m_Scripts =
113 new Dictionary<UUID, IScriptInstance>(); 114 new Dictionary<UUID, IScriptInstance>();
114 115
116 private OpenMetaverse.ReaderWriterLockSlim m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
117
115 // Maps the asset ID to the assembly 118 // Maps the asset ID to the assembly
116 119
117 private Dictionary<UUID, string> m_Assemblies = 120 private Dictionary<UUID, string> m_Assemblies =
@@ -134,6 +137,71 @@ namespace OpenSim.Region.ScriptEngine.XEngine
134 IWorkItemResult m_CurrentCompile = null; 137 IWorkItemResult m_CurrentCompile = null;
135 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>(); 138 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>();
136 139
140 private void lockScriptsForRead(bool locked)
141 {
142 if (locked)
143 {
144 if (m_scriptsLock.RecursiveReadCount > 0)
145 {
146 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.");
147 m_scriptsLock.ExitReadLock();
148 }
149 if (m_scriptsLock.RecursiveWriteCount > 0)
150 {
151 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
152 m_scriptsLock.ExitWriteLock();
153 }
154
155 while (!m_scriptsLock.TryEnterReadLock(60000))
156 {
157 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.");
158 if (m_scriptsLock.IsWriteLockHeld)
159 {
160 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
161 }
162 }
163 }
164 else
165 {
166 if (m_scriptsLock.RecursiveReadCount > 0)
167 {
168 m_scriptsLock.ExitReadLock();
169 }
170 }
171 }
172 private void lockScriptsForWrite(bool locked)
173 {
174 if (locked)
175 {
176 if (m_scriptsLock.RecursiveReadCount > 0)
177 {
178 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.");
179 m_scriptsLock.ExitReadLock();
180 }
181 if (m_scriptsLock.RecursiveWriteCount > 0)
182 {
183 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
184 m_scriptsLock.ExitWriteLock();
185 }
186
187 while (!m_scriptsLock.TryEnterWriteLock(60000))
188 {
189 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.");
190 if (m_scriptsLock.IsWriteLockHeld)
191 {
192 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
193 }
194 }
195 }
196 else
197 {
198 if (m_scriptsLock.RecursiveWriteCount > 0)
199 {
200 m_scriptsLock.ExitWriteLock();
201 }
202 }
203 }
204
137 public string ScriptEngineName 205 public string ScriptEngineName
138 { 206 {
139 get { return "XEngine"; } 207 get { return "XEngine"; }
@@ -516,44 +584,37 @@ namespace OpenSim.Region.ScriptEngine.XEngine
516 { 584 {
517 if (!m_Enabled) 585 if (!m_Enabled)
518 return; 586 return;
519 587 lockScriptsForRead(true);
520 lock (m_Scripts) 588 foreach (IScriptInstance instance in m_Scripts.Values)
521 { 589 {
522 m_log.InfoFormat( 590 // Force a final state save
523 "[XEngine]: Shutting down {0} scripts in {1}", m_Scripts.Count, m_Scene.RegionInfo.RegionName); 591 //
524 592 if (m_Assemblies.ContainsKey(instance.AssetID))
525 foreach (IScriptInstance instance in m_Scripts.Values)
526 { 593 {
527 // Force a final state save 594 string assembly = m_Assemblies[instance.AssetID];
528 // 595 instance.SaveState(assembly);
529 if (m_Assemblies.ContainsKey(instance.AssetID)) 596 }
530 {
531 string assembly = m_Assemblies[instance.AssetID];
532 instance.SaveState(assembly);
533 }
534 597
535 // Clear the event queue and abort the instance thread 598 // Clear the event queue and abort the instance thread
536 // 599 //
537 instance.ClearQueue(); 600 instance.ClearQueue();
538 instance.Stop(0); 601 instance.Stop(0);
539 602
540 // Release events, timer, etc 603 // Release events, timer, etc
541 // 604 //
542 instance.DestroyScriptInstance(); 605 instance.DestroyScriptInstance();
543 606
544 // Unload scripts and app domains. 607 // Unload scripts and app domains
545 // Must be done explicitly because they have infinite 608 // Must be done explicitly because they have infinite
546 // lifetime. 609 // lifetime
547 // However, don't bother to do this if the simulator is shutting 610 //
548 // down since it takes a long time with many scripts. 611 if (!m_SimulatorShuttingDown)
549 if (!m_SimulatorShuttingDown) 612 {
613 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
614 if (m_DomainScripts[instance.AppDomain].Count == 0)
550 { 615 {
551 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 616 m_DomainScripts.Remove(instance.AppDomain);
552 if (m_DomainScripts[instance.AppDomain].Count == 0) 617 UnloadAppDomain(instance.AppDomain);
553 {
554 m_DomainScripts.Remove(instance.AppDomain);
555 UnloadAppDomain(instance.AppDomain);
556 }
557 } 618 }
558 } 619 }
559 620
@@ -562,6 +623,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
562 m_Assemblies.Clear(); 623 m_Assemblies.Clear();
563 m_DomainScripts.Clear(); 624 m_DomainScripts.Clear();
564 } 625 }
626 lockScriptsForRead(false);
627 lockScriptsForWrite(true);
628 m_Scripts.Clear();
629 lockScriptsForWrite(false);
630 m_PrimObjects.Clear();
631 m_Assemblies.Clear();
632 m_DomainScripts.Clear();
633
565 lock (m_ScriptEngines) 634 lock (m_ScriptEngines)
566 { 635 {
567 m_ScriptEngines.Remove(this); 636 m_ScriptEngines.Remove(this);
@@ -626,22 +695,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
626 695
627 List<IScriptInstance> instances = new List<IScriptInstance>(); 696 List<IScriptInstance> instances = new List<IScriptInstance>();
628 697
629 lock (m_Scripts) 698 lockScriptsForRead(true);
630 { 699 foreach (IScriptInstance instance in m_Scripts.Values)
631 foreach (IScriptInstance instance in m_Scripts.Values)
632 instances.Add(instance); 700 instances.Add(instance);
633 } 701 lockScriptsForRead(false);
634 702
635 foreach (IScriptInstance i in instances) 703 foreach (IScriptInstance i in instances)
636 { 704 {
637 string assembly = String.Empty; 705 string assembly = String.Empty;
638 706
639 lock (m_Scripts) 707
640 {
641 if (!m_Assemblies.ContainsKey(i.AssetID)) 708 if (!m_Assemblies.ContainsKey(i.AssetID))
642 continue; 709 continue;
643 assembly = m_Assemblies[i.AssetID]; 710 assembly = m_Assemblies[i.AssetID];
644 } 711
645 712
646 i.SaveState(assembly); 713 i.SaveState(assembly);
647 } 714 }
@@ -985,92 +1052,95 @@ namespace OpenSim.Region.ScriptEngine.XEngine
985 } 1052 }
986 1053
987 ScriptInstance instance = null; 1054 ScriptInstance instance = null;
988 lock (m_Scripts) 1055 // Create the object record
1056 lockScriptsForRead(true);
1057 if ((!m_Scripts.ContainsKey(itemID)) ||
1058 (m_Scripts[itemID].AssetID != assetID))
989 { 1059 {
990 // Create the object record 1060 lockScriptsForRead(false);
991 1061
992 if ((!m_Scripts.ContainsKey(itemID)) || 1062 UUID appDomain = assetID;
993 (m_Scripts[itemID].AssetID != assetID))
994 {
995 UUID appDomain = assetID;
996 1063
997 if (part.ParentGroup.IsAttachment) 1064 if (part.ParentGroup.IsAttachment)
998 appDomain = part.ParentGroup.RootPart.UUID; 1065 appDomain = part.ParentGroup.RootPart.UUID;
999 1066
1000 if (!m_AppDomains.ContainsKey(appDomain)) 1067 if (!m_AppDomains.ContainsKey(appDomain))
1068 {
1069 try
1001 { 1070 {
1002 try 1071 AppDomainSetup appSetup = new AppDomainSetup();
1003 { 1072 appSetup.PrivateBinPath = Path.Combine(
1004 AppDomainSetup appSetup = new AppDomainSetup(); 1073 m_ScriptEnginesPath,
1005 appSetup.PrivateBinPath = Path.Combine( 1074 m_Scene.RegionInfo.RegionID.ToString());
1006 m_ScriptEnginesPath, 1075
1007 m_Scene.RegionInfo.RegionID.ToString()); 1076 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
1008 1077 Evidence evidence = new Evidence(baseEvidence);
1009 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 1078
1010 Evidence evidence = new Evidence(baseEvidence); 1079 AppDomain sandbox;
1011 1080 if (m_AppDomainLoading)
1012 AppDomain sandbox; 1081 sandbox = AppDomain.CreateDomain(
1013 if (m_AppDomainLoading) 1082 m_Scene.RegionInfo.RegionID.ToString(),
1014 sandbox = AppDomain.CreateDomain( 1083 evidence, appSetup);
1015 m_Scene.RegionInfo.RegionID.ToString(), 1084 else
1016 evidence, appSetup); 1085 sandbox = AppDomain.CurrentDomain;
1017 else 1086
1018 sandbox = AppDomain.CurrentDomain; 1087 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1019 1088 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1020 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); 1089 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1021 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); 1090 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1022 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet"); 1091 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1023 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet); 1092 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1024 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement); 1093 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1025 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup; 1094
1026 //sandbox.SetAppDomainPolicy(sandboxPolicy); 1095 m_AppDomains[appDomain] = sandbox;
1027 1096
1028 m_AppDomains[appDomain] = sandbox; 1097 m_AppDomains[appDomain].AssemblyResolve +=
1029 1098 new ResolveEventHandler(
1030 m_AppDomains[appDomain].AssemblyResolve += 1099 AssemblyResolver.OnAssemblyResolve);
1031 new ResolveEventHandler( 1100 m_DomainScripts[appDomain] = new List<UUID>();
1032 AssemblyResolver.OnAssemblyResolve); 1101 }
1033 m_DomainScripts[appDomain] = new List<UUID>(); 1102 catch (Exception e)
1034 } 1103 {
1035 catch (Exception e) 1104 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
1105 m_ScriptErrorMessage += "Exception creating app domain:\n";
1106 m_ScriptFailCount++;
1107 lock (m_AddingAssemblies)
1036 { 1108 {
1037 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); 1109 m_AddingAssemblies[assembly]--;
1038 m_ScriptErrorMessage += "Exception creating app domain:\n";
1039 m_ScriptFailCount++;
1040 lock (m_AddingAssemblies)
1041 {
1042 m_AddingAssemblies[assembly]--;
1043 }
1044 return false;
1045 } 1110 }
1111 return false;
1046 } 1112 }
1047 m_DomainScripts[appDomain].Add(itemID); 1113 }
1048 1114 m_DomainScripts[appDomain].Add(itemID);
1049 instance = new ScriptInstance(this, part, 1115
1050 itemID, assetID, assembly, 1116 instance = new ScriptInstance(this, part,
1051 m_AppDomains[appDomain], 1117 itemID, assetID, assembly,
1052 part.ParentGroup.RootPart.Name, 1118 m_AppDomains[appDomain],
1053 item.Name, startParam, postOnRez, 1119 part.ParentGroup.RootPart.Name,
1054 stateSource, m_MaxScriptQueue); 1120 item.Name, startParam, postOnRez,
1055 1121 stateSource, m_MaxScriptQueue);
1056 m_log.DebugFormat( 1122
1057 "[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", 1123 m_log.DebugFormat(
1058 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, 1124 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1125 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
1059 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); 1126 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1060 1127
1061 if (presence != null) 1128 if (presence != null)
1062 { 1129 {
1063 ShowScriptSaveResponse(item.OwnerID, 1130 ShowScriptSaveResponse(item.OwnerID,
1064 assetID, "Compile successful", true); 1131 assetID, "Compile successful", true);
1065 }
1066
1067 instance.AppDomain = appDomain;
1068 instance.LineMap = linemap;
1069
1070 m_Scripts[itemID] = instance;
1071 } 1132 }
1072 }
1073 1133
1134 instance.AppDomain = appDomain;
1135 instance.LineMap = linemap;
1136 lockScriptsForWrite(true);
1137 m_Scripts[itemID] = instance;
1138 lockScriptsForWrite(false);
1139 }
1140 else
1141 {
1142 lockScriptsForRead(false);
1143 }
1074 lock (m_PrimObjects) 1144 lock (m_PrimObjects)
1075 { 1145 {
1076 if (!m_PrimObjects.ContainsKey(localID)) 1146 if (!m_PrimObjects.ContainsKey(localID))
@@ -1089,9 +1159,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1089 m_AddingAssemblies[assembly]--; 1159 m_AddingAssemblies[assembly]--;
1090 } 1160 }
1091 1161
1092 if (instance != null) 1162 if (instance!=null)
1093 instance.Init(); 1163 instance.Init();
1094 1164
1095 return true; 1165 return true;
1096 } 1166 }
1097 1167
@@ -1104,20 +1174,31 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1104 m_CompileDict.Remove(itemID); 1174 m_CompileDict.Remove(itemID);
1105 } 1175 }
1106 1176
1107 IScriptInstance instance = null; 1177 lockScriptsForRead(true);
1108 1178 // Do we even have it?
1109 lock (m_Scripts) 1179 if (!m_Scripts.ContainsKey(itemID))
1110 { 1180 {
1111 // Do we even have it? 1181 // Do we even have it?
1112 if (!m_Scripts.ContainsKey(itemID)) 1182 if (!m_Scripts.ContainsKey(itemID))
1113 return; 1183 return;
1114 1184
1115 instance = m_Scripts[itemID]; 1185 lockScriptsForRead(false);
1186 lockScriptsForWrite(true);
1116 m_Scripts.Remove(itemID); 1187 m_Scripts.Remove(itemID);
1188 lockScriptsForWrite(false);
1189
1190 return;
1117 } 1191 }
1192
1118 1193
1194 IScriptInstance instance=m_Scripts[itemID];
1195 lockScriptsForRead(false);
1196 lockScriptsForWrite(true);
1197 m_Scripts.Remove(itemID);
1198 lockScriptsForWrite(false);
1119 instance.ClearQueue(); 1199 instance.ClearQueue();
1120 instance.Stop(0); 1200 instance.Stop(0);
1201
1121// bool objectRemoved = false; 1202// bool objectRemoved = false;
1122 1203
1123 lock (m_PrimObjects) 1204 lock (m_PrimObjects)
@@ -1153,10 +1234,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1153 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 1234 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
1154 if (handlerObjectRemoved != null) 1235 if (handlerObjectRemoved != null)
1155 { 1236 {
1156 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID); 1237 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
1157 handlerObjectRemoved(part.UUID); 1238 handlerObjectRemoved(part.UUID);
1158 } 1239 }
1159 1240
1241 CleanAssemblies();
1242
1160 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 1243 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
1161 if (handlerScriptRemoved != null) 1244 if (handlerScriptRemoved != null)
1162 handlerScriptRemoved(itemID); 1245 handlerScriptRemoved(itemID);
@@ -1298,7 +1381,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1298 return false; 1381 return false;
1299 1382
1300 uuids = m_PrimObjects[localID]; 1383 uuids = m_PrimObjects[localID];
1301 } 1384
1302 1385
1303 foreach (UUID itemID in uuids) 1386 foreach (UUID itemID in uuids)
1304 { 1387 {
@@ -1316,6 +1399,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1316 result = true; 1399 result = true;
1317 } 1400 }
1318 } 1401 }
1402 }
1319 1403
1320 return result; 1404 return result;
1321 } 1405 }
@@ -1417,12 +1501,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1417 private IScriptInstance GetInstance(UUID itemID) 1501 private IScriptInstance GetInstance(UUID itemID)
1418 { 1502 {
1419 IScriptInstance instance; 1503 IScriptInstance instance;
1420 lock (m_Scripts) 1504 lockScriptsForRead(true);
1505 if (!m_Scripts.ContainsKey(itemID))
1421 { 1506 {
1422 if (!m_Scripts.ContainsKey(itemID)) 1507 lockScriptsForRead(false);
1423 return null; 1508 return null;
1424 instance = m_Scripts[itemID];
1425 } 1509 }
1510 instance = m_Scripts[itemID];
1511 lockScriptsForRead(false);
1426 return instance; 1512 return instance;
1427 } 1513 }
1428 1514
@@ -1446,6 +1532,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1446 return false; 1532 return false;
1447 } 1533 }
1448 1534
1535 [DebuggerNonUserCode]
1449 public void ApiResetScript(UUID itemID) 1536 public void ApiResetScript(UUID itemID)
1450 { 1537 {
1451 IScriptInstance instance = GetInstance(itemID); 1538 IScriptInstance instance = GetInstance(itemID);
@@ -1497,6 +1584,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1497 return UUID.Zero; 1584 return UUID.Zero;
1498 } 1585 }
1499 1586
1587 [DebuggerNonUserCode]
1500 public void SetState(UUID itemID, string newState) 1588 public void SetState(UUID itemID, string newState)
1501 { 1589 {
1502 IScriptInstance instance = GetInstance(itemID); 1590 IScriptInstance instance = GetInstance(itemID);
@@ -1519,11 +1607,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1519 1607
1520 List<IScriptInstance> instances = new List<IScriptInstance>(); 1608 List<IScriptInstance> instances = new List<IScriptInstance>();
1521 1609
1522 lock (m_Scripts) 1610 lockScriptsForRead(true);
1523 { 1611 foreach (IScriptInstance instance in m_Scripts.Values)
1524 foreach (IScriptInstance instance in m_Scripts.Values)
1525 instances.Add(instance); 1612 instances.Add(instance);
1526 } 1613 lockScriptsForRead(false);
1527 1614
1528 foreach (IScriptInstance i in instances) 1615 foreach (IScriptInstance i in instances)
1529 { 1616 {
@@ -1908,5 +1995,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1908// else 1995// else
1909// m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID); 1996// m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID);
1910 } 1997 }
1998
1999 public bool HasScript(UUID itemID, out bool running)
2000 {
2001 running = true;
2002
2003 IScriptInstance instance = GetInstance(itemID);
2004 if (instance == null)
2005 return false;
2006
2007 running = instance.Running;
2008 return true;
2009 }
1911 } 2010 }
1912} \ No newline at end of file 2011}