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.cs360
1 files changed, 226 insertions, 134 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 01aebb6..35a0200 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;
@@ -126,6 +127,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
126 private Dictionary<UUID, IScriptInstance> m_Scripts = 127 private Dictionary<UUID, IScriptInstance> m_Scripts =
127 new Dictionary<UUID, IScriptInstance>(); 128 new Dictionary<UUID, IScriptInstance>();
128 129
130 private OpenMetaverse.ReaderWriterLockSlim m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
131
129 // Maps the asset ID to the assembly 132 // Maps the asset ID to the assembly
130 133
131 private Dictionary<UUID, string> m_Assemblies = 134 private Dictionary<UUID, string> m_Assemblies =
@@ -148,6 +151,71 @@ namespace OpenSim.Region.ScriptEngine.XEngine
148 IWorkItemResult m_CurrentCompile = null; 151 IWorkItemResult m_CurrentCompile = null;
149 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>(); 152 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>();
150 153
154 private void lockScriptsForRead(bool locked)
155 {
156 if (locked)
157 {
158 if (m_scriptsLock.RecursiveReadCount > 0)
159 {
160 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.");
161 m_scriptsLock.ExitReadLock();
162 }
163 if (m_scriptsLock.RecursiveWriteCount > 0)
164 {
165 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
166 m_scriptsLock.ExitWriteLock();
167 }
168
169 while (!m_scriptsLock.TryEnterReadLock(60000))
170 {
171 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.");
172 if (m_scriptsLock.IsWriteLockHeld)
173 {
174 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
175 }
176 }
177 }
178 else
179 {
180 if (m_scriptsLock.RecursiveReadCount > 0)
181 {
182 m_scriptsLock.ExitReadLock();
183 }
184 }
185 }
186 private void lockScriptsForWrite(bool locked)
187 {
188 if (locked)
189 {
190 if (m_scriptsLock.RecursiveReadCount > 0)
191 {
192 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.");
193 m_scriptsLock.ExitReadLock();
194 }
195 if (m_scriptsLock.RecursiveWriteCount > 0)
196 {
197 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
198 m_scriptsLock.ExitWriteLock();
199 }
200
201 while (!m_scriptsLock.TryEnterWriteLock(60000))
202 {
203 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.");
204 if (m_scriptsLock.IsWriteLockHeld)
205 {
206 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
207 }
208 }
209 }
210 else
211 {
212 if (m_scriptsLock.RecursiveWriteCount > 0)
213 {
214 m_scriptsLock.ExitWriteLock();
215 }
216 }
217 }
218
151 public string ScriptEngineName 219 public string ScriptEngineName
152 { 220 {
153 get { return "XEngine"; } 221 get { return "XEngine"; }
@@ -574,52 +642,57 @@ namespace OpenSim.Region.ScriptEngine.XEngine
574 { 642 {
575 if (!m_Enabled) 643 if (!m_Enabled)
576 return; 644 return;
645 lockScriptsForRead(true);
577 646
578 lock (m_Scripts) 647 List<IScriptInstance> instancesToDel = new List<IScriptInstance>(m_Scripts.Values);
579 {
580 m_log.InfoFormat(
581 "[XEngine]: Shutting down {0} scripts in {1}", m_Scripts.Count, m_Scene.RegionInfo.RegionName);
582 648
583 foreach (IScriptInstance instance in m_Scripts.Values) 649// foreach (IScriptInstance instance in m_Scripts.Values)
650 foreach (IScriptInstance instance in instancesToDel)
651 {
652 // Force a final state save
653 //
654 if (m_Assemblies.ContainsKey(instance.AssetID))
584 { 655 {
585 // Force a final state save 656 string assembly = m_Assemblies[instance.AssetID];
586 // 657 instance.SaveState(assembly);
587 if (m_Assemblies.ContainsKey(instance.AssetID)) 658 }
588 {
589 string assembly = m_Assemblies[instance.AssetID];
590 instance.SaveState(assembly);
591 }
592 659
593 // Clear the event queue and abort the instance thread 660 // Clear the event queue and abort the instance thread
594 // 661 //
595 instance.ClearQueue(); 662 instance.ClearQueue();
596 instance.Stop(0); 663 instance.Stop(0);
597 664
598 // Release events, timer, etc 665 // Release events, timer, etc
599 // 666 //
600 instance.DestroyScriptInstance(); 667 instance.DestroyScriptInstance();
601 668
602 // Unload scripts and app domains. 669 // Unload scripts and app domains
603 // Must be done explicitly because they have infinite 670 // Must be done explicitly because they have infinite
604 // lifetime. 671 // lifetime
605 // However, don't bother to do this if the simulator is shutting 672 //
606 // down since it takes a long time with many scripts. 673// if (!m_SimulatorShuttingDown)
607 if (!m_SimulatorShuttingDown) 674 {
675 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
676 if (m_DomainScripts[instance.AppDomain].Count == 0)
608 { 677 {
609 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 678 m_DomainScripts.Remove(instance.AppDomain);
610 if (m_DomainScripts[instance.AppDomain].Count == 0) 679 UnloadAppDomain(instance.AppDomain);
611 {
612 m_DomainScripts.Remove(instance.AppDomain);
613 UnloadAppDomain(instance.AppDomain);
614 }
615 } 680 }
616 } 681 }
617 682
618 m_Scripts.Clear(); 683// m_Scripts.Clear();
619 m_PrimObjects.Clear(); 684// m_PrimObjects.Clear();
620 m_Assemblies.Clear(); 685// m_Assemblies.Clear();
621 m_DomainScripts.Clear(); 686// m_DomainScripts.Clear();
622 } 687 }
688 lockScriptsForRead(false);
689 lockScriptsForWrite(true);
690 m_Scripts.Clear();
691 lockScriptsForWrite(false);
692 m_PrimObjects.Clear();
693 m_Assemblies.Clear();
694 m_DomainScripts.Clear();
695
623 lock (m_ScriptEngines) 696 lock (m_ScriptEngines)
624 { 697 {
625 m_ScriptEngines.Remove(this); 698 m_ScriptEngines.Remove(this);
@@ -684,22 +757,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
684 757
685 List<IScriptInstance> instances = new List<IScriptInstance>(); 758 List<IScriptInstance> instances = new List<IScriptInstance>();
686 759
687 lock (m_Scripts) 760 lockScriptsForRead(true);
688 { 761 foreach (IScriptInstance instance in m_Scripts.Values)
689 foreach (IScriptInstance instance in m_Scripts.Values)
690 instances.Add(instance); 762 instances.Add(instance);
691 } 763 lockScriptsForRead(false);
692 764
693 foreach (IScriptInstance i in instances) 765 foreach (IScriptInstance i in instances)
694 { 766 {
695 string assembly = String.Empty; 767 string assembly = String.Empty;
696 768
697 lock (m_Scripts) 769
698 {
699 if (!m_Assemblies.ContainsKey(i.AssetID)) 770 if (!m_Assemblies.ContainsKey(i.AssetID))
700 continue; 771 continue;
701 assembly = m_Assemblies[i.AssetID]; 772 assembly = m_Assemblies[i.AssetID];
702 } 773
703 774
704 i.SaveState(assembly); 775 i.SaveState(assembly);
705 } 776 }
@@ -1086,96 +1157,99 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1086 } 1157 }
1087 1158
1088 ScriptInstance instance = null; 1159 ScriptInstance instance = null;
1089 lock (m_Scripts) 1160 // Create the object record
1161 lockScriptsForRead(true);
1162 if ((!m_Scripts.ContainsKey(itemID)) ||
1163 (m_Scripts[itemID].AssetID != assetID))
1090 { 1164 {
1091 // Create the object record 1165 lockScriptsForRead(false);
1092 if ((!m_Scripts.ContainsKey(itemID)) || 1166
1093 (m_Scripts[itemID].AssetID != assetID)) 1167 UUID appDomain = assetID;
1094 {
1095 UUID appDomain = assetID;
1096 1168
1097 if (part.ParentGroup.IsAttachment) 1169 if (part.ParentGroup.IsAttachment)
1098 appDomain = part.ParentGroup.RootPart.UUID; 1170 appDomain = part.ParentGroup.RootPart.UUID;
1099 1171
1100 if (!m_AppDomains.ContainsKey(appDomain)) 1172 if (!m_AppDomains.ContainsKey(appDomain))
1173 {
1174 try
1101 { 1175 {
1102 try 1176 AppDomainSetup appSetup = new AppDomainSetup();
1103 { 1177 appSetup.PrivateBinPath = Path.Combine(
1104 AppDomainSetup appSetup = new AppDomainSetup(); 1178 m_ScriptEnginesPath,
1105 appSetup.PrivateBinPath = Path.Combine( 1179 m_Scene.RegionInfo.RegionID.ToString());
1106 m_ScriptEnginesPath,
1107 m_Scene.RegionInfo.RegionID.ToString());
1108 1180
1109 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 1181 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
1110 Evidence evidence = new Evidence(baseEvidence); 1182 Evidence evidence = new Evidence(baseEvidence);
1111 1183
1112 AppDomain sandbox; 1184 AppDomain sandbox;
1113 if (m_AppDomainLoading) 1185 if (m_AppDomainLoading)
1114 { 1186 {
1115 sandbox = AppDomain.CreateDomain( 1187 sandbox = AppDomain.CreateDomain(
1116 m_Scene.RegionInfo.RegionID.ToString(), 1188 m_Scene.RegionInfo.RegionID.ToString(),
1117 evidence, appSetup); 1189 evidence, appSetup);
1118 sandbox.AssemblyResolve += 1190 m_AppDomains[appDomain].AssemblyResolve +=
1119 new ResolveEventHandler( 1191 new ResolveEventHandler(
1120 AssemblyResolver.OnAssemblyResolve); 1192 AssemblyResolver.OnAssemblyResolve);
1121 }
1122 else
1123 {
1124 sandbox = AppDomain.CurrentDomain;
1125 }
1126
1127 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1128 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1129 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1130 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1131 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1132 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1133 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1134
1135 m_AppDomains[appDomain] = sandbox;
1136
1137 m_DomainScripts[appDomain] = new List<UUID>();
1138 } 1193 }
1139 catch (Exception e) 1194 else
1140 { 1195 {
1141 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); 1196 sandbox = AppDomain.CurrentDomain;
1142 m_ScriptErrorMessage += "Exception creating app domain:\n";
1143 m_ScriptFailCount++;
1144 lock (m_AddingAssemblies)
1145 {
1146 m_AddingAssemblies[assembly]--;
1147 }
1148 return false;
1149 } 1197 }
1150 }
1151 m_DomainScripts[appDomain].Add(itemID);
1152
1153 instance = new ScriptInstance(this, part,
1154 itemID, assetID, assembly,
1155 m_AppDomains[appDomain],
1156 part.ParentGroup.RootPart.Name,
1157 item.Name, startParam, postOnRez,
1158 stateSource, m_MaxScriptQueue);
1159
1160// if (DebugLevel >= 1)
1161 m_log.DebugFormat(
1162 "[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}",
1163 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
1164 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1165 1198
1166 if (presence != null) 1199 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1200 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1201 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1202 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1203 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1204 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1205 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1206
1207 m_AppDomains[appDomain] = sandbox;
1208
1209 m_DomainScripts[appDomain] = new List<UUID>();
1210 }
1211 catch (Exception e)
1167 { 1212 {
1168 ShowScriptSaveResponse(item.OwnerID, 1213 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
1169 assetID, "Compile successful", true); 1214 m_ScriptErrorMessage += "Exception creating app domain:\n";
1215 m_ScriptFailCount++;
1216 lock (m_AddingAssemblies)
1217 {
1218 m_AddingAssemblies[assembly]--;
1219 }
1220 return false;
1170 } 1221 }
1222 }
1223 m_DomainScripts[appDomain].Add(itemID);
1224
1225 instance = new ScriptInstance(this, part,
1226 itemID, assetID, assembly,
1227 m_AppDomains[appDomain],
1228 part.ParentGroup.RootPart.Name,
1229 item.Name, startParam, postOnRez,
1230 stateSource, m_MaxScriptQueue);
1231
1232 m_log.DebugFormat(
1233 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1234 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
1235 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1171 1236
1172 instance.AppDomain = appDomain; 1237 if (presence != null)
1173 instance.LineMap = linemap; 1238 {
1174 1239 ShowScriptSaveResponse(item.OwnerID,
1175 m_Scripts[itemID] = instance; 1240 assetID, "Compile successful", true);
1176 } 1241 }
1177 }
1178 1242
1243 instance.AppDomain = appDomain;
1244 instance.LineMap = linemap;
1245 lockScriptsForWrite(true);
1246 m_Scripts[itemID] = instance;
1247 lockScriptsForWrite(false);
1248 }
1249 else
1250 {
1251 lockScriptsForRead(false);
1252 }
1179 lock (m_PrimObjects) 1253 lock (m_PrimObjects)
1180 { 1254 {
1181 if (!m_PrimObjects.ContainsKey(localID)) 1255 if (!m_PrimObjects.ContainsKey(localID))
@@ -1193,9 +1267,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1193 m_AddingAssemblies[assembly]--; 1267 m_AddingAssemblies[assembly]--;
1194 } 1268 }
1195 1269
1196 if (instance != null) 1270 if (instance!=null)
1197 instance.Init(); 1271 instance.Init();
1198 1272
1199 return true; 1273 return true;
1200 } 1274 }
1201 1275
@@ -1208,18 +1282,28 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1208 m_CompileDict.Remove(itemID); 1282 m_CompileDict.Remove(itemID);
1209 } 1283 }
1210 1284
1211 IScriptInstance instance = null; 1285 lockScriptsForRead(true);
1212 1286 // Do we even have it?
1213 lock (m_Scripts) 1287 if (!m_Scripts.ContainsKey(itemID))
1214 { 1288 {
1215 // Do we even have it? 1289 // Do we even have it?
1216 if (!m_Scripts.ContainsKey(itemID)) 1290 if (!m_Scripts.ContainsKey(itemID))
1217 return; 1291 return;
1218 1292
1219 instance = m_Scripts[itemID]; 1293 lockScriptsForRead(false);
1294 lockScriptsForWrite(true);
1220 m_Scripts.Remove(itemID); 1295 m_Scripts.Remove(itemID);
1296 lockScriptsForWrite(false);
1297
1298 return;
1221 } 1299 }
1300
1222 1301
1302 IScriptInstance instance=m_Scripts[itemID];
1303 lockScriptsForRead(false);
1304 lockScriptsForWrite(true);
1305 m_Scripts.Remove(itemID);
1306 lockScriptsForWrite(false);
1223 instance.ClearQueue(); 1307 instance.ClearQueue();
1224 1308
1225 // Give the script some time to finish processing its last event. Simply aborting the script thread can 1309 // Give the script some time to finish processing its last event. Simply aborting the script thread can
@@ -1258,8 +1342,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1258 1342
1259 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 1343 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
1260 if (handlerObjectRemoved != null) 1344 if (handlerObjectRemoved != null)
1261 handlerObjectRemoved(instance.ObjectID); 1345 {
1346 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
1347 handlerObjectRemoved(part.UUID);
1348 }
1262 1349
1350 CleanAssemblies();
1351
1263 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 1352 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
1264 if (handlerScriptRemoved != null) 1353 if (handlerScriptRemoved != null)
1265 handlerScriptRemoved(itemID); 1354 handlerScriptRemoved(itemID);
@@ -1520,12 +1609,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1520 private IScriptInstance GetInstance(UUID itemID) 1609 private IScriptInstance GetInstance(UUID itemID)
1521 { 1610 {
1522 IScriptInstance instance; 1611 IScriptInstance instance;
1523 lock (m_Scripts) 1612 lockScriptsForRead(true);
1613 if (!m_Scripts.ContainsKey(itemID))
1524 { 1614 {
1525 if (!m_Scripts.ContainsKey(itemID)) 1615 lockScriptsForRead(false);
1526 return null; 1616 return null;
1527 instance = m_Scripts[itemID];
1528 } 1617 }
1618 instance = m_Scripts[itemID];
1619 lockScriptsForRead(false);
1529 return instance; 1620 return instance;
1530 } 1621 }
1531 1622
@@ -1549,6 +1640,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1549 return false; 1640 return false;
1550 } 1641 }
1551 1642
1643 [DebuggerNonUserCode]
1552 public void ApiResetScript(UUID itemID) 1644 public void ApiResetScript(UUID itemID)
1553 { 1645 {
1554 IScriptInstance instance = GetInstance(itemID); 1646 IScriptInstance instance = GetInstance(itemID);
@@ -1604,6 +1696,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1604 return UUID.Zero; 1696 return UUID.Zero;
1605 } 1697 }
1606 1698
1699 [DebuggerNonUserCode]
1607 public void SetState(UUID itemID, string newState) 1700 public void SetState(UUID itemID, string newState)
1608 { 1701 {
1609 IScriptInstance instance = GetInstance(itemID); 1702 IScriptInstance instance = GetInstance(itemID);
@@ -1626,11 +1719,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1626 1719
1627 List<IScriptInstance> instances = new List<IScriptInstance>(); 1720 List<IScriptInstance> instances = new List<IScriptInstance>();
1628 1721
1629 lock (m_Scripts) 1722 lockScriptsForRead(true);
1630 { 1723 foreach (IScriptInstance instance in m_Scripts.Values)
1631 foreach (IScriptInstance instance in m_Scripts.Values)
1632 instances.Add(instance); 1724 instances.Add(instance);
1633 } 1725 lockScriptsForRead(false);
1634 1726
1635 foreach (IScriptInstance i in instances) 1727 foreach (IScriptInstance i in instances)
1636 { 1728 {