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.cs358
1 files changed, 225 insertions, 133 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 2dba029..f6cb7df 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;
@@ -128,6 +129,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
128 private Dictionary<UUID, IScriptInstance> m_Scripts = 129 private Dictionary<UUID, IScriptInstance> m_Scripts =
129 new Dictionary<UUID, IScriptInstance>(); 130 new Dictionary<UUID, IScriptInstance>();
130 131
132 private OpenMetaverse.ReaderWriterLockSlim m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
133
131 // Maps the asset ID to the assembly 134 // Maps the asset ID to the assembly
132 135
133 private Dictionary<UUID, string> m_Assemblies = 136 private Dictionary<UUID, string> m_Assemblies =
@@ -150,6 +153,71 @@ namespace OpenSim.Region.ScriptEngine.XEngine
150 IWorkItemResult m_CurrentCompile = null; 153 IWorkItemResult m_CurrentCompile = null;
151 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>(); 154 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>();
152 155
156 private void lockScriptsForRead(bool locked)
157 {
158 if (locked)
159 {
160 if (m_scriptsLock.RecursiveReadCount > 0)
161 {
162 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.");
163 m_scriptsLock.ExitReadLock();
164 }
165 if (m_scriptsLock.RecursiveWriteCount > 0)
166 {
167 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
168 m_scriptsLock.ExitWriteLock();
169 }
170
171 while (!m_scriptsLock.TryEnterReadLock(60000))
172 {
173 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.");
174 if (m_scriptsLock.IsWriteLockHeld)
175 {
176 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
177 }
178 }
179 }
180 else
181 {
182 if (m_scriptsLock.RecursiveReadCount > 0)
183 {
184 m_scriptsLock.ExitReadLock();
185 }
186 }
187 }
188 private void lockScriptsForWrite(bool locked)
189 {
190 if (locked)
191 {
192 if (m_scriptsLock.RecursiveReadCount > 0)
193 {
194 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.");
195 m_scriptsLock.ExitReadLock();
196 }
197 if (m_scriptsLock.RecursiveWriteCount > 0)
198 {
199 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
200 m_scriptsLock.ExitWriteLock();
201 }
202
203 while (!m_scriptsLock.TryEnterWriteLock(60000))
204 {
205 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.");
206 if (m_scriptsLock.IsWriteLockHeld)
207 {
208 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
209 }
210 }
211 }
212 else
213 {
214 if (m_scriptsLock.RecursiveWriteCount > 0)
215 {
216 m_scriptsLock.ExitWriteLock();
217 }
218 }
219 }
220
153 public string ScriptEngineName 221 public string ScriptEngineName
154 { 222 {
155 get { return "XEngine"; } 223 get { return "XEngine"; }
@@ -576,52 +644,57 @@ namespace OpenSim.Region.ScriptEngine.XEngine
576 { 644 {
577 if (!m_Enabled) 645 if (!m_Enabled)
578 return; 646 return;
647 lockScriptsForRead(true);
579 648
580 lock (m_Scripts) 649 List<IScriptInstance> instancesToDel = new List<IScriptInstance>(m_Scripts.Values);
581 {
582 m_log.InfoFormat(
583 "[XEngine]: Shutting down {0} scripts in {1}", m_Scripts.Count, m_Scene.RegionInfo.RegionName);
584 650
585 foreach (IScriptInstance instance in m_Scripts.Values) 651// foreach (IScriptInstance instance in m_Scripts.Values)
652 foreach (IScriptInstance instance in instancesToDel)
653 {
654 // Force a final state save
655 //
656 if (m_Assemblies.ContainsKey(instance.AssetID))
586 { 657 {
587 // Force a final state save 658 string assembly = m_Assemblies[instance.AssetID];
588 // 659 instance.SaveState(assembly);
589 if (m_Assemblies.ContainsKey(instance.AssetID)) 660 }
590 {
591 string assembly = m_Assemblies[instance.AssetID];
592 instance.SaveState(assembly);
593 }
594 661
595 // Clear the event queue and abort the instance thread 662 // Clear the event queue and abort the instance thread
596 // 663 //
597 instance.ClearQueue(); 664 instance.ClearQueue();
598 instance.Stop(0); 665 instance.Stop(0);
599 666
600 // Release events, timer, etc 667 // Release events, timer, etc
601 // 668 //
602 instance.DestroyScriptInstance(); 669 instance.DestroyScriptInstance();
603 670
604 // Unload scripts and app domains. 671 // Unload scripts and app domains
605 // Must be done explicitly because they have infinite 672 // Must be done explicitly because they have infinite
606 // lifetime. 673 // lifetime
607 // However, don't bother to do this if the simulator is shutting 674 //
608 // down since it takes a long time with many scripts. 675// if (!m_SimulatorShuttingDown)
609 if (!m_SimulatorShuttingDown) 676 {
677 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
678 if (m_DomainScripts[instance.AppDomain].Count == 0)
610 { 679 {
611 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 680 m_DomainScripts.Remove(instance.AppDomain);
612 if (m_DomainScripts[instance.AppDomain].Count == 0) 681 UnloadAppDomain(instance.AppDomain);
613 {
614 m_DomainScripts.Remove(instance.AppDomain);
615 UnloadAppDomain(instance.AppDomain);
616 }
617 } 682 }
618 } 683 }
619 684
620 m_Scripts.Clear(); 685// m_Scripts.Clear();
621 m_PrimObjects.Clear(); 686// m_PrimObjects.Clear();
622 m_Assemblies.Clear(); 687// m_Assemblies.Clear();
623 m_DomainScripts.Clear(); 688// m_DomainScripts.Clear();
624 } 689 }
690 lockScriptsForRead(false);
691 lockScriptsForWrite(true);
692 m_Scripts.Clear();
693 lockScriptsForWrite(false);
694 m_PrimObjects.Clear();
695 m_Assemblies.Clear();
696 m_DomainScripts.Clear();
697
625 lock (m_ScriptEngines) 698 lock (m_ScriptEngines)
626 { 699 {
627 m_ScriptEngines.Remove(this); 700 m_ScriptEngines.Remove(this);
@@ -690,22 +763,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
690 763
691 List<IScriptInstance> instances = new List<IScriptInstance>(); 764 List<IScriptInstance> instances = new List<IScriptInstance>();
692 765
693 lock (m_Scripts) 766 lockScriptsForRead(true);
694 { 767 foreach (IScriptInstance instance in m_Scripts.Values)
695 foreach (IScriptInstance instance in m_Scripts.Values)
696 instances.Add(instance); 768 instances.Add(instance);
697 } 769 lockScriptsForRead(false);
698 770
699 foreach (IScriptInstance i in instances) 771 foreach (IScriptInstance i in instances)
700 { 772 {
701 string assembly = String.Empty; 773 string assembly = String.Empty;
702 774
703 lock (m_Scripts) 775
704 {
705 if (!m_Assemblies.ContainsKey(i.AssetID)) 776 if (!m_Assemblies.ContainsKey(i.AssetID))
706 continue; 777 continue;
707 assembly = m_Assemblies[i.AssetID]; 778 assembly = m_Assemblies[i.AssetID];
708 } 779
709 780
710 i.SaveState(assembly); 781 i.SaveState(assembly);
711 } 782 }
@@ -1092,96 +1163,99 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1092 } 1163 }
1093 1164
1094 ScriptInstance instance = null; 1165 ScriptInstance instance = null;
1095 lock (m_Scripts) 1166 // Create the object record
1167 lockScriptsForRead(true);
1168 if ((!m_Scripts.ContainsKey(itemID)) ||
1169 (m_Scripts[itemID].AssetID != assetID))
1096 { 1170 {
1097 // Create the object record 1171 lockScriptsForRead(false);
1098 if ((!m_Scripts.ContainsKey(itemID)) ||
1099 (m_Scripts[itemID].AssetID != assetID))
1100 {
1101 UUID appDomain = assetID;
1102 1172
1103 if (part.ParentGroup.IsAttachment) 1173 UUID appDomain = assetID;
1104 appDomain = part.ParentGroup.RootPart.UUID;
1105 1174
1106 if (!m_AppDomains.ContainsKey(appDomain)) 1175 if (part.ParentGroup.IsAttachment)
1107 { 1176 appDomain = part.ParentGroup.RootPart.UUID;
1108 try
1109 {
1110 AppDomainSetup appSetup = new AppDomainSetup();
1111 appSetup.PrivateBinPath = Path.Combine(
1112 m_ScriptEnginesPath,
1113 m_Scene.RegionInfo.RegionID.ToString());
1114 1177
1115 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 1178 if (!m_AppDomains.ContainsKey(appDomain))
1116 Evidence evidence = new Evidence(baseEvidence); 1179 {
1180 try
1181 {
1182 AppDomainSetup appSetup = new AppDomainSetup();
1183 appSetup.PrivateBinPath = Path.Combine(
1184 m_ScriptEnginesPath,
1185 m_Scene.RegionInfo.RegionID.ToString());
1117 1186
1118 AppDomain sandbox; 1187 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
1119 if (m_AppDomainLoading) 1188 Evidence evidence = new Evidence(baseEvidence);
1120 {
1121 sandbox = AppDomain.CreateDomain(
1122 m_Scene.RegionInfo.RegionID.ToString(),
1123 evidence, appSetup);
1124 sandbox.AssemblyResolve +=
1125 new ResolveEventHandler(
1126 AssemblyResolver.OnAssemblyResolve);
1127 }
1128 else
1129 {
1130 sandbox = AppDomain.CurrentDomain;
1131 }
1132
1133 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1134 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1135 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1136 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1137 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1138 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1139 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1140
1141 m_AppDomains[appDomain] = sandbox;
1142 1189
1143 m_DomainScripts[appDomain] = new List<UUID>(); 1190 AppDomain sandbox;
1191 if (m_AppDomainLoading)
1192 {
1193 sandbox = AppDomain.CreateDomain(
1194 m_Scene.RegionInfo.RegionID.ToString(),
1195 evidence, appSetup);
1196 m_AppDomains[appDomain].AssemblyResolve +=
1197 new ResolveEventHandler(
1198 AssemblyResolver.OnAssemblyResolve);
1144 } 1199 }
1145 catch (Exception e) 1200 else
1146 { 1201 {
1147 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); 1202 sandbox = AppDomain.CurrentDomain;
1148 m_ScriptErrorMessage += "Exception creating app domain:\n";
1149 m_ScriptFailCount++;
1150 lock (m_AddingAssemblies)
1151 {
1152 m_AddingAssemblies[assembly]--;
1153 }
1154 return false;
1155 } 1203 }
1156 }
1157 m_DomainScripts[appDomain].Add(itemID);
1158
1159 instance = new ScriptInstance(this, part,
1160 itemID, assetID, assembly,
1161 m_AppDomains[appDomain],
1162 part.ParentGroup.RootPart.Name,
1163 item.Name, startParam, postOnRez,
1164 stateSource, m_MaxScriptQueue);
1165
1166// if (DebugLevel >= 1)
1167 m_log.DebugFormat(
1168 "[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}",
1169 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
1170 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1171 1204
1172 if (presence != null) 1205 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1206 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1207 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1208 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1209 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1210 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1211 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1212
1213 m_AppDomains[appDomain] = sandbox;
1214
1215 m_DomainScripts[appDomain] = new List<UUID>();
1216 }
1217 catch (Exception e)
1173 { 1218 {
1174 ShowScriptSaveResponse(item.OwnerID, 1219 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
1175 assetID, "Compile successful", true); 1220 m_ScriptErrorMessage += "Exception creating app domain:\n";
1221 m_ScriptFailCount++;
1222 lock (m_AddingAssemblies)
1223 {
1224 m_AddingAssemblies[assembly]--;
1225 }
1226 return false;
1176 } 1227 }
1228 }
1229 m_DomainScripts[appDomain].Add(itemID);
1230
1231 instance = new ScriptInstance(this, part,
1232 itemID, assetID, assembly,
1233 m_AppDomains[appDomain],
1234 part.ParentGroup.RootPart.Name,
1235 item.Name, startParam, postOnRez,
1236 stateSource, m_MaxScriptQueue);
1237
1238 m_log.DebugFormat(
1239 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1240 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
1241 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1177 1242
1178 instance.AppDomain = appDomain; 1243 if (presence != null)
1179 instance.LineMap = linemap; 1244 {
1180 1245 ShowScriptSaveResponse(item.OwnerID,
1181 m_Scripts[itemID] = instance; 1246 assetID, "Compile successful", true);
1182 } 1247 }
1183 }
1184 1248
1249 instance.AppDomain = appDomain;
1250 instance.LineMap = linemap;
1251 lockScriptsForWrite(true);
1252 m_Scripts[itemID] = instance;
1253 lockScriptsForWrite(false);
1254 }
1255 else
1256 {
1257 lockScriptsForRead(false);
1258 }
1185 lock (m_PrimObjects) 1259 lock (m_PrimObjects)
1186 { 1260 {
1187 if (!m_PrimObjects.ContainsKey(localID)) 1261 if (!m_PrimObjects.ContainsKey(localID))
@@ -1199,7 +1273,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1199 m_AddingAssemblies[assembly]--; 1273 m_AddingAssemblies[assembly]--;
1200 } 1274 }
1201 1275
1202 if (instance != null) 1276 if (instance!=null)
1203 instance.Init(); 1277 instance.Init();
1204 1278
1205 bool runIt; 1279 bool runIt;
@@ -1222,18 +1296,28 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1222 m_CompileDict.Remove(itemID); 1296 m_CompileDict.Remove(itemID);
1223 } 1297 }
1224 1298
1225 IScriptInstance instance = null; 1299 lockScriptsForRead(true);
1226 1300 // Do we even have it?
1227 lock (m_Scripts) 1301 if (!m_Scripts.ContainsKey(itemID))
1228 { 1302 {
1229 // Do we even have it? 1303 // Do we even have it?
1230 if (!m_Scripts.ContainsKey(itemID)) 1304 if (!m_Scripts.ContainsKey(itemID))
1231 return; 1305 return;
1232 1306
1233 instance = m_Scripts[itemID]; 1307 lockScriptsForRead(false);
1308 lockScriptsForWrite(true);
1234 m_Scripts.Remove(itemID); 1309 m_Scripts.Remove(itemID);
1310 lockScriptsForWrite(false);
1311
1312 return;
1235 } 1313 }
1314
1236 1315
1316 IScriptInstance instance=m_Scripts[itemID];
1317 lockScriptsForRead(false);
1318 lockScriptsForWrite(true);
1319 m_Scripts.Remove(itemID);
1320 lockScriptsForWrite(false);
1237 instance.ClearQueue(); 1321 instance.ClearQueue();
1238 1322
1239 // Give the script some time to finish processing its last event. Simply aborting the script thread can 1323 // Give the script some time to finish processing its last event. Simply aborting the script thread can
@@ -1272,8 +1356,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1272 1356
1273 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 1357 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
1274 if (handlerObjectRemoved != null) 1358 if (handlerObjectRemoved != null)
1275 handlerObjectRemoved(instance.ObjectID); 1359 {
1360 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
1361 handlerObjectRemoved(part.UUID);
1362 }
1276 1363
1364 CleanAssemblies();
1365
1277 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 1366 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
1278 if (handlerScriptRemoved != null) 1367 if (handlerScriptRemoved != null)
1279 handlerScriptRemoved(itemID); 1368 handlerScriptRemoved(itemID);
@@ -1534,12 +1623,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1534 private IScriptInstance GetInstance(UUID itemID) 1623 private IScriptInstance GetInstance(UUID itemID)
1535 { 1624 {
1536 IScriptInstance instance; 1625 IScriptInstance instance;
1537 lock (m_Scripts) 1626 lockScriptsForRead(true);
1627 if (!m_Scripts.ContainsKey(itemID))
1538 { 1628 {
1539 if (!m_Scripts.ContainsKey(itemID)) 1629 lockScriptsForRead(false);
1540 return null; 1630 return null;
1541 instance = m_Scripts[itemID];
1542 } 1631 }
1632 instance = m_Scripts[itemID];
1633 lockScriptsForRead(false);
1543 return instance; 1634 return instance;
1544 } 1635 }
1545 1636
@@ -1563,6 +1654,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1563 return false; 1654 return false;
1564 } 1655 }
1565 1656
1657 [DebuggerNonUserCode]
1566 public void ApiResetScript(UUID itemID) 1658 public void ApiResetScript(UUID itemID)
1567 { 1659 {
1568 IScriptInstance instance = GetInstance(itemID); 1660 IScriptInstance instance = GetInstance(itemID);
@@ -1624,6 +1716,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1624 return UUID.Zero; 1716 return UUID.Zero;
1625 } 1717 }
1626 1718
1719 [DebuggerNonUserCode]
1627 public void SetState(UUID itemID, string newState) 1720 public void SetState(UUID itemID, string newState)
1628 { 1721 {
1629 IScriptInstance instance = GetInstance(itemID); 1722 IScriptInstance instance = GetInstance(itemID);
@@ -1646,11 +1739,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1646 1739
1647 List<IScriptInstance> instances = new List<IScriptInstance>(); 1740 List<IScriptInstance> instances = new List<IScriptInstance>();
1648 1741
1649 lock (m_Scripts) 1742 lockScriptsForRead(true);
1650 { 1743 foreach (IScriptInstance instance in m_Scripts.Values)
1651 foreach (IScriptInstance instance in m_Scripts.Values)
1652 instances.Add(instance); 1744 instances.Add(instance);
1653 } 1745 lockScriptsForRead(false);
1654 1746
1655 foreach (IScriptInstance i in instances) 1747 foreach (IScriptInstance i in instances)
1656 { 1748 {