aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/XEngine
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine/XEngine')
-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 a05650a..eee5d7b 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 }
@@ -1094,96 +1165,99 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1094 } 1165 }
1095 1166
1096 ScriptInstance instance = null; 1167 ScriptInstance instance = null;
1097 lock (m_Scripts) 1168 // Create the object record
1169 lockScriptsForRead(true);
1170 if ((!m_Scripts.ContainsKey(itemID)) ||
1171 (m_Scripts[itemID].AssetID != assetID))
1098 { 1172 {
1099 // Create the object record 1173 lockScriptsForRead(false);
1100 if ((!m_Scripts.ContainsKey(itemID)) ||
1101 (m_Scripts[itemID].AssetID != assetID))
1102 {
1103 UUID appDomain = assetID;
1104 1174
1105 if (part.ParentGroup.IsAttachment) 1175 UUID appDomain = assetID;
1106 appDomain = part.ParentGroup.RootPart.UUID;
1107 1176
1108 if (!m_AppDomains.ContainsKey(appDomain)) 1177 if (part.ParentGroup.IsAttachment)
1109 { 1178 appDomain = part.ParentGroup.RootPart.UUID;
1110 try
1111 {
1112 AppDomainSetup appSetup = new AppDomainSetup();
1113 appSetup.PrivateBinPath = Path.Combine(
1114 m_ScriptEnginesPath,
1115 m_Scene.RegionInfo.RegionID.ToString());
1116 1179
1117 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 1180 if (!m_AppDomains.ContainsKey(appDomain))
1118 Evidence evidence = new Evidence(baseEvidence); 1181 {
1182 try
1183 {
1184 AppDomainSetup appSetup = new AppDomainSetup();
1185 appSetup.PrivateBinPath = Path.Combine(
1186 m_ScriptEnginesPath,
1187 m_Scene.RegionInfo.RegionID.ToString());
1119 1188
1120 AppDomain sandbox; 1189 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
1121 if (m_AppDomainLoading) 1190 Evidence evidence = new Evidence(baseEvidence);
1122 {
1123 sandbox = AppDomain.CreateDomain(
1124 m_Scene.RegionInfo.RegionID.ToString(),
1125 evidence, appSetup);
1126 sandbox.AssemblyResolve +=
1127 new ResolveEventHandler(
1128 AssemblyResolver.OnAssemblyResolve);
1129 }
1130 else
1131 {
1132 sandbox = AppDomain.CurrentDomain;
1133 }
1134
1135 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1136 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1137 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1138 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1139 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1140 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1141 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1142
1143 m_AppDomains[appDomain] = sandbox;
1144 1191
1145 m_DomainScripts[appDomain] = new List<UUID>(); 1192 AppDomain sandbox;
1193 if (m_AppDomainLoading)
1194 {
1195 sandbox = AppDomain.CreateDomain(
1196 m_Scene.RegionInfo.RegionID.ToString(),
1197 evidence, appSetup);
1198 m_AppDomains[appDomain].AssemblyResolve +=
1199 new ResolveEventHandler(
1200 AssemblyResolver.OnAssemblyResolve);
1146 } 1201 }
1147 catch (Exception e) 1202 else
1148 { 1203 {
1149 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); 1204 sandbox = AppDomain.CurrentDomain;
1150 m_ScriptErrorMessage += "Exception creating app domain:\n";
1151 m_ScriptFailCount++;
1152 lock (m_AddingAssemblies)
1153 {
1154 m_AddingAssemblies[assembly]--;
1155 }
1156 return false;
1157 } 1205 }
1158 }
1159 m_DomainScripts[appDomain].Add(itemID);
1160
1161 instance = new ScriptInstance(this, part,
1162 itemID, assetID, assembly,
1163 m_AppDomains[appDomain],
1164 part.ParentGroup.RootPart.Name,
1165 item.Name, startParam, postOnRez,
1166 stateSource, m_MaxScriptQueue);
1167
1168// if (DebugLevel >= 1)
1169// m_log.DebugFormat(
1170// "[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}",
1171// part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
1172// part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1173 1206
1174 if (presence != null) 1207 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1208 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1209 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1210 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1211 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1212 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1213 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1214
1215 m_AppDomains[appDomain] = sandbox;
1216
1217 m_DomainScripts[appDomain] = new List<UUID>();
1218 }
1219 catch (Exception e)
1175 { 1220 {
1176 ShowScriptSaveResponse(item.OwnerID, 1221 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
1177 assetID, "Compile successful", true); 1222 m_ScriptErrorMessage += "Exception creating app domain:\n";
1223 m_ScriptFailCount++;
1224 lock (m_AddingAssemblies)
1225 {
1226 m_AddingAssemblies[assembly]--;
1227 }
1228 return false;
1178 } 1229 }
1230 }
1231 m_DomainScripts[appDomain].Add(itemID);
1232
1233 instance = new ScriptInstance(this, part,
1234 itemID, assetID, assembly,
1235 m_AppDomains[appDomain],
1236 part.ParentGroup.RootPart.Name,
1237 item.Name, startParam, postOnRez,
1238 stateSource, m_MaxScriptQueue);
1239
1240// m_log.DebugFormat(
1241// "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1242// part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
1243// part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1179 1244
1180 instance.AppDomain = appDomain; 1245 if (presence != null)
1181 instance.LineMap = linemap; 1246 {
1182 1247 ShowScriptSaveResponse(item.OwnerID,
1183 m_Scripts[itemID] = instance; 1248 assetID, "Compile successful", true);
1184 } 1249 }
1185 }
1186 1250
1251 instance.AppDomain = appDomain;
1252 instance.LineMap = linemap;
1253 lockScriptsForWrite(true);
1254 m_Scripts[itemID] = instance;
1255 lockScriptsForWrite(false);
1256 }
1257 else
1258 {
1259 lockScriptsForRead(false);
1260 }
1187 lock (m_PrimObjects) 1261 lock (m_PrimObjects)
1188 { 1262 {
1189 if (!m_PrimObjects.ContainsKey(localID)) 1263 if (!m_PrimObjects.ContainsKey(localID))
@@ -1201,7 +1275,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1201 m_AddingAssemblies[assembly]--; 1275 m_AddingAssemblies[assembly]--;
1202 } 1276 }
1203 1277
1204 if (instance != null) 1278 if (instance!=null)
1205 instance.Init(); 1279 instance.Init();
1206 1280
1207 bool runIt; 1281 bool runIt;
@@ -1224,18 +1298,28 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1224 m_CompileDict.Remove(itemID); 1298 m_CompileDict.Remove(itemID);
1225 } 1299 }
1226 1300
1227 IScriptInstance instance = null; 1301 lockScriptsForRead(true);
1228 1302 // Do we even have it?
1229 lock (m_Scripts) 1303 if (!m_Scripts.ContainsKey(itemID))
1230 { 1304 {
1231 // Do we even have it? 1305 // Do we even have it?
1232 if (!m_Scripts.ContainsKey(itemID)) 1306 if (!m_Scripts.ContainsKey(itemID))
1233 return; 1307 return;
1234 1308
1235 instance = m_Scripts[itemID]; 1309 lockScriptsForRead(false);
1310 lockScriptsForWrite(true);
1236 m_Scripts.Remove(itemID); 1311 m_Scripts.Remove(itemID);
1312 lockScriptsForWrite(false);
1313
1314 return;
1237 } 1315 }
1316
1238 1317
1318 IScriptInstance instance=m_Scripts[itemID];
1319 lockScriptsForRead(false);
1320 lockScriptsForWrite(true);
1321 m_Scripts.Remove(itemID);
1322 lockScriptsForWrite(false);
1239 instance.ClearQueue(); 1323 instance.ClearQueue();
1240 1324
1241 // Give the script some time to finish processing its last event. Simply aborting the script thread can 1325 // Give the script some time to finish processing its last event. Simply aborting the script thread can
@@ -1274,8 +1358,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1274 1358
1275 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 1359 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
1276 if (handlerObjectRemoved != null) 1360 if (handlerObjectRemoved != null)
1277 handlerObjectRemoved(instance.ObjectID); 1361 {
1362 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
1363 handlerObjectRemoved(part.UUID);
1364 }
1278 1365
1366 CleanAssemblies();
1367
1279 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 1368 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
1280 if (handlerScriptRemoved != null) 1369 if (handlerScriptRemoved != null)
1281 handlerScriptRemoved(itemID); 1370 handlerScriptRemoved(itemID);
@@ -1536,12 +1625,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1536 private IScriptInstance GetInstance(UUID itemID) 1625 private IScriptInstance GetInstance(UUID itemID)
1537 { 1626 {
1538 IScriptInstance instance; 1627 IScriptInstance instance;
1539 lock (m_Scripts) 1628 lockScriptsForRead(true);
1629 if (!m_Scripts.ContainsKey(itemID))
1540 { 1630 {
1541 if (!m_Scripts.ContainsKey(itemID)) 1631 lockScriptsForRead(false);
1542 return null; 1632 return null;
1543 instance = m_Scripts[itemID];
1544 } 1633 }
1634 instance = m_Scripts[itemID];
1635 lockScriptsForRead(false);
1545 return instance; 1636 return instance;
1546 } 1637 }
1547 1638
@@ -1565,6 +1656,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1565 return false; 1656 return false;
1566 } 1657 }
1567 1658
1659 [DebuggerNonUserCode]
1568 public void ApiResetScript(UUID itemID) 1660 public void ApiResetScript(UUID itemID)
1569 { 1661 {
1570 IScriptInstance instance = GetInstance(itemID); 1662 IScriptInstance instance = GetInstance(itemID);
@@ -1626,6 +1718,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1626 return UUID.Zero; 1718 return UUID.Zero;
1627 } 1719 }
1628 1720
1721 [DebuggerNonUserCode]
1629 public void SetState(UUID itemID, string newState) 1722 public void SetState(UUID itemID, string newState)
1630 { 1723 {
1631 IScriptInstance instance = GetInstance(itemID); 1724 IScriptInstance instance = GetInstance(itemID);
@@ -1648,11 +1741,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1648 1741
1649 List<IScriptInstance> instances = new List<IScriptInstance>(); 1742 List<IScriptInstance> instances = new List<IScriptInstance>();
1650 1743
1651 lock (m_Scripts) 1744 lockScriptsForRead(true);
1652 { 1745 foreach (IScriptInstance instance in m_Scripts.Values)
1653 foreach (IScriptInstance instance in m_Scripts.Values)
1654 instances.Add(instance); 1746 instances.Add(instance);
1655 } 1747 lockScriptsForRead(false);
1656 1748
1657 foreach (IScriptInstance i in instances) 1749 foreach (IScriptInstance i in instances)
1658 { 1750 {