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.cs348
1 files changed, 218 insertions, 130 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index efcae94..2886344 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;
@@ -120,6 +121,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
120 private Dictionary<UUID, IScriptInstance> m_Scripts = 121 private Dictionary<UUID, IScriptInstance> m_Scripts =
121 new Dictionary<UUID, IScriptInstance>(); 122 new Dictionary<UUID, IScriptInstance>();
122 123
124 private OpenMetaverse.ReaderWriterLockSlim m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
125
123 // Maps the asset ID to the assembly 126 // Maps the asset ID to the assembly
124 127
125 private Dictionary<UUID, string> m_Assemblies = 128 private Dictionary<UUID, string> m_Assemblies =
@@ -142,6 +145,71 @@ namespace OpenSim.Region.ScriptEngine.XEngine
142 IWorkItemResult m_CurrentCompile = null; 145 IWorkItemResult m_CurrentCompile = null;
143 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>(); 146 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>();
144 147
148 private void lockScriptsForRead(bool locked)
149 {
150 if (locked)
151 {
152 if (m_scriptsLock.RecursiveReadCount > 0)
153 {
154 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.");
155 m_scriptsLock.ExitReadLock();
156 }
157 if (m_scriptsLock.RecursiveWriteCount > 0)
158 {
159 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
160 m_scriptsLock.ExitWriteLock();
161 }
162
163 while (!m_scriptsLock.TryEnterReadLock(60000))
164 {
165 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.");
166 if (m_scriptsLock.IsWriteLockHeld)
167 {
168 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
169 }
170 }
171 }
172 else
173 {
174 if (m_scriptsLock.RecursiveReadCount > 0)
175 {
176 m_scriptsLock.ExitReadLock();
177 }
178 }
179 }
180 private void lockScriptsForWrite(bool locked)
181 {
182 if (locked)
183 {
184 if (m_scriptsLock.RecursiveReadCount > 0)
185 {
186 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.");
187 m_scriptsLock.ExitReadLock();
188 }
189 if (m_scriptsLock.RecursiveWriteCount > 0)
190 {
191 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
192 m_scriptsLock.ExitWriteLock();
193 }
194
195 while (!m_scriptsLock.TryEnterWriteLock(60000))
196 {
197 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.");
198 if (m_scriptsLock.IsWriteLockHeld)
199 {
200 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
201 }
202 }
203 }
204 else
205 {
206 if (m_scriptsLock.RecursiveWriteCount > 0)
207 {
208 m_scriptsLock.ExitWriteLock();
209 }
210 }
211 }
212
145 public string ScriptEngineName 213 public string ScriptEngineName
146 { 214 {
147 get { return "XEngine"; } 215 get { return "XEngine"; }
@@ -567,44 +635,37 @@ namespace OpenSim.Region.ScriptEngine.XEngine
567 { 635 {
568 if (!m_Enabled) 636 if (!m_Enabled)
569 return; 637 return;
570 638 lockScriptsForRead(true);
571 lock (m_Scripts) 639 foreach (IScriptInstance instance in m_Scripts.Values)
572 { 640 {
573 m_log.InfoFormat( 641 // Force a final state save
574 "[XEngine]: Shutting down {0} scripts in {1}", m_Scripts.Count, m_Scene.RegionInfo.RegionName); 642 //
575 643 if (m_Assemblies.ContainsKey(instance.AssetID))
576 foreach (IScriptInstance instance in m_Scripts.Values)
577 { 644 {
578 // Force a final state save 645 string assembly = m_Assemblies[instance.AssetID];
579 // 646 instance.SaveState(assembly);
580 if (m_Assemblies.ContainsKey(instance.AssetID)) 647 }
581 {
582 string assembly = m_Assemblies[instance.AssetID];
583 instance.SaveState(assembly);
584 }
585 648
586 // Clear the event queue and abort the instance thread 649 // Clear the event queue and abort the instance thread
587 // 650 //
588 instance.ClearQueue(); 651 instance.ClearQueue();
589 instance.Stop(0); 652 instance.Stop(0);
590 653
591 // Release events, timer, etc 654 // Release events, timer, etc
592 // 655 //
593 instance.DestroyScriptInstance(); 656 instance.DestroyScriptInstance();
594 657
595 // Unload scripts and app domains. 658 // Unload scripts and app domains
596 // Must be done explicitly because they have infinite 659 // Must be done explicitly because they have infinite
597 // lifetime. 660 // lifetime
598 // However, don't bother to do this if the simulator is shutting 661 //
599 // down since it takes a long time with many scripts. 662 if (!m_SimulatorShuttingDown)
600 if (!m_SimulatorShuttingDown) 663 {
664 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
665 if (m_DomainScripts[instance.AppDomain].Count == 0)
601 { 666 {
602 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 667 m_DomainScripts.Remove(instance.AppDomain);
603 if (m_DomainScripts[instance.AppDomain].Count == 0) 668 UnloadAppDomain(instance.AppDomain);
604 {
605 m_DomainScripts.Remove(instance.AppDomain);
606 UnloadAppDomain(instance.AppDomain);
607 }
608 } 669 }
609 } 670 }
610 671
@@ -613,6 +674,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
613 m_Assemblies.Clear(); 674 m_Assemblies.Clear();
614 m_DomainScripts.Clear(); 675 m_DomainScripts.Clear();
615 } 676 }
677 lockScriptsForRead(false);
678 lockScriptsForWrite(true);
679 m_Scripts.Clear();
680 lockScriptsForWrite(false);
681 m_PrimObjects.Clear();
682 m_Assemblies.Clear();
683 m_DomainScripts.Clear();
684
616 lock (m_ScriptEngines) 685 lock (m_ScriptEngines)
617 { 686 {
618 m_ScriptEngines.Remove(this); 687 m_ScriptEngines.Remove(this);
@@ -677,22 +746,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
677 746
678 List<IScriptInstance> instances = new List<IScriptInstance>(); 747 List<IScriptInstance> instances = new List<IScriptInstance>();
679 748
680 lock (m_Scripts) 749 lockScriptsForRead(true);
681 { 750 foreach (IScriptInstance instance in m_Scripts.Values)
682 foreach (IScriptInstance instance in m_Scripts.Values)
683 instances.Add(instance); 751 instances.Add(instance);
684 } 752 lockScriptsForRead(false);
685 753
686 foreach (IScriptInstance i in instances) 754 foreach (IScriptInstance i in instances)
687 { 755 {
688 string assembly = String.Empty; 756 string assembly = String.Empty;
689 757
690 lock (m_Scripts) 758
691 {
692 if (!m_Assemblies.ContainsKey(i.AssetID)) 759 if (!m_Assemblies.ContainsKey(i.AssetID))
693 continue; 760 continue;
694 assembly = m_Assemblies[i.AssetID]; 761 assembly = m_Assemblies[i.AssetID];
695 } 762
696 763
697 i.SaveState(assembly); 764 i.SaveState(assembly);
698 } 765 }
@@ -1079,96 +1146,99 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1079 } 1146 }
1080 1147
1081 ScriptInstance instance = null; 1148 ScriptInstance instance = null;
1082 lock (m_Scripts) 1149 // Create the object record
1150 lockScriptsForRead(true);
1151 if ((!m_Scripts.ContainsKey(itemID)) ||
1152 (m_Scripts[itemID].AssetID != assetID))
1083 { 1153 {
1084 // Create the object record 1154 lockScriptsForRead(false);
1085 if ((!m_Scripts.ContainsKey(itemID)) ||
1086 (m_Scripts[itemID].AssetID != assetID))
1087 {
1088 UUID appDomain = assetID;
1089 1155
1090 if (part.ParentGroup.IsAttachment) 1156 UUID appDomain = assetID;
1091 appDomain = part.ParentGroup.RootPart.UUID;
1092 1157
1093 if (!m_AppDomains.ContainsKey(appDomain)) 1158 if (part.ParentGroup.IsAttachment)
1094 { 1159 appDomain = part.ParentGroup.RootPart.UUID;
1095 try
1096 {
1097 AppDomainSetup appSetup = new AppDomainSetup();
1098 appSetup.PrivateBinPath = Path.Combine(
1099 m_ScriptEnginesPath,
1100 m_Scene.RegionInfo.RegionID.ToString());
1101 1160
1102 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 1161 if (!m_AppDomains.ContainsKey(appDomain))
1103 Evidence evidence = new Evidence(baseEvidence); 1162 {
1163 try
1164 {
1165 AppDomainSetup appSetup = new AppDomainSetup();
1166 appSetup.PrivateBinPath = Path.Combine(
1167 m_ScriptEnginesPath,
1168 m_Scene.RegionInfo.RegionID.ToString());
1104 1169
1105 AppDomain sandbox; 1170 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
1106 if (m_AppDomainLoading) 1171 Evidence evidence = new Evidence(baseEvidence);
1107 {
1108 sandbox = AppDomain.CreateDomain(
1109 m_Scene.RegionInfo.RegionID.ToString(),
1110 evidence, appSetup);
1111 sandbox.AssemblyResolve +=
1112 new ResolveEventHandler(
1113 AssemblyResolver.OnAssemblyResolve);
1114 }
1115 else
1116 {
1117 sandbox = AppDomain.CurrentDomain;
1118 }
1119
1120 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1121 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1122 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1123 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1124 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1125 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1126 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1127
1128 m_AppDomains[appDomain] = sandbox;
1129 1172
1130 m_DomainScripts[appDomain] = new List<UUID>(); 1173 AppDomain sandbox;
1174 if (m_AppDomainLoading)
1175 {
1176 sandbox = AppDomain.CreateDomain(
1177 m_Scene.RegionInfo.RegionID.ToString(),
1178 evidence, appSetup);
1179 m_AppDomains[appDomain].AssemblyResolve +=
1180 new ResolveEventHandler(
1181 AssemblyResolver.OnAssemblyResolve);
1131 } 1182 }
1132 catch (Exception e) 1183 else
1133 { 1184 {
1134 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); 1185 sandbox = AppDomain.CurrentDomain;
1135 m_ScriptErrorMessage += "Exception creating app domain:\n";
1136 m_ScriptFailCount++;
1137 lock (m_AddingAssemblies)
1138 {
1139 m_AddingAssemblies[assembly]--;
1140 }
1141 return false;
1142 } 1186 }
1143 }
1144 m_DomainScripts[appDomain].Add(itemID);
1145
1146 instance = new ScriptInstance(this, part,
1147 itemID, assetID, assembly,
1148 m_AppDomains[appDomain],
1149 part.ParentGroup.RootPart.Name,
1150 item.Name, startParam, postOnRez,
1151 stateSource, m_MaxScriptQueue);
1152
1153// if (DebugLevel >= 1)
1154 m_log.DebugFormat(
1155 "[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}",
1156 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
1157 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1158 1187
1159 if (presence != null) 1188 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1189 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1190 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1191 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1192 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1193 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1194 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1195
1196 m_AppDomains[appDomain] = sandbox;
1197
1198 m_DomainScripts[appDomain] = new List<UUID>();
1199 }
1200 catch (Exception e)
1160 { 1201 {
1161 ShowScriptSaveResponse(item.OwnerID, 1202 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
1162 assetID, "Compile successful", true); 1203 m_ScriptErrorMessage += "Exception creating app domain:\n";
1204 m_ScriptFailCount++;
1205 lock (m_AddingAssemblies)
1206 {
1207 m_AddingAssemblies[assembly]--;
1208 }
1209 return false;
1163 } 1210 }
1211 }
1212 m_DomainScripts[appDomain].Add(itemID);
1213
1214 instance = new ScriptInstance(this, part,
1215 itemID, assetID, assembly,
1216 m_AppDomains[appDomain],
1217 part.ParentGroup.RootPart.Name,
1218 item.Name, startParam, postOnRez,
1219 stateSource, m_MaxScriptQueue);
1220
1221 m_log.DebugFormat(
1222 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1223 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
1224 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1164 1225
1165 instance.AppDomain = appDomain; 1226 if (presence != null)
1166 instance.LineMap = linemap; 1227 {
1167 1228 ShowScriptSaveResponse(item.OwnerID,
1168 m_Scripts[itemID] = instance; 1229 assetID, "Compile successful", true);
1169 } 1230 }
1170 }
1171 1231
1232 instance.AppDomain = appDomain;
1233 instance.LineMap = linemap;
1234 lockScriptsForWrite(true);
1235 m_Scripts[itemID] = instance;
1236 lockScriptsForWrite(false);
1237 }
1238 else
1239 {
1240 lockScriptsForRead(false);
1241 }
1172 lock (m_PrimObjects) 1242 lock (m_PrimObjects)
1173 { 1243 {
1174 if (!m_PrimObjects.ContainsKey(localID)) 1244 if (!m_PrimObjects.ContainsKey(localID))
@@ -1186,9 +1256,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1186 m_AddingAssemblies[assembly]--; 1256 m_AddingAssemblies[assembly]--;
1187 } 1257 }
1188 1258
1189 if (instance != null) 1259 if (instance!=null)
1190 instance.Init(); 1260 instance.Init();
1191 1261
1192 return true; 1262 return true;
1193 } 1263 }
1194 1264
@@ -1201,18 +1271,28 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1201 m_CompileDict.Remove(itemID); 1271 m_CompileDict.Remove(itemID);
1202 } 1272 }
1203 1273
1204 IScriptInstance instance = null; 1274 lockScriptsForRead(true);
1205 1275 // Do we even have it?
1206 lock (m_Scripts) 1276 if (!m_Scripts.ContainsKey(itemID))
1207 { 1277 {
1208 // Do we even have it? 1278 // Do we even have it?
1209 if (!m_Scripts.ContainsKey(itemID)) 1279 if (!m_Scripts.ContainsKey(itemID))
1210 return; 1280 return;
1211 1281
1212 instance = m_Scripts[itemID]; 1282 lockScriptsForRead(false);
1283 lockScriptsForWrite(true);
1213 m_Scripts.Remove(itemID); 1284 m_Scripts.Remove(itemID);
1285 lockScriptsForWrite(false);
1286
1287 return;
1214 } 1288 }
1289
1215 1290
1291 IScriptInstance instance=m_Scripts[itemID];
1292 lockScriptsForRead(false);
1293 lockScriptsForWrite(true);
1294 m_Scripts.Remove(itemID);
1295 lockScriptsForWrite(false);
1216 instance.ClearQueue(); 1296 instance.ClearQueue();
1217 1297
1218 // Give the script some time to finish processing its last event. Simply aborting the script thread can 1298 // Give the script some time to finish processing its last event. Simply aborting the script thread can
@@ -1251,8 +1331,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1251 1331
1252 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 1332 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
1253 if (handlerObjectRemoved != null) 1333 if (handlerObjectRemoved != null)
1254 handlerObjectRemoved(instance.ObjectID); 1334 {
1335 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
1336 handlerObjectRemoved(part.UUID);
1337 }
1255 1338
1339 CleanAssemblies();
1340
1256 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 1341 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
1257 if (handlerScriptRemoved != null) 1342 if (handlerScriptRemoved != null)
1258 handlerScriptRemoved(itemID); 1343 handlerScriptRemoved(itemID);
@@ -1513,12 +1598,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1513 private IScriptInstance GetInstance(UUID itemID) 1598 private IScriptInstance GetInstance(UUID itemID)
1514 { 1599 {
1515 IScriptInstance instance; 1600 IScriptInstance instance;
1516 lock (m_Scripts) 1601 lockScriptsForRead(true);
1602 if (!m_Scripts.ContainsKey(itemID))
1517 { 1603 {
1518 if (!m_Scripts.ContainsKey(itemID)) 1604 lockScriptsForRead(false);
1519 return null; 1605 return null;
1520 instance = m_Scripts[itemID];
1521 } 1606 }
1607 instance = m_Scripts[itemID];
1608 lockScriptsForRead(false);
1522 return instance; 1609 return instance;
1523 } 1610 }
1524 1611
@@ -1549,6 +1636,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1549 return false; 1636 return false;
1550 } 1637 }
1551 1638
1639 [DebuggerNonUserCode]
1552 public void ApiResetScript(UUID itemID) 1640 public void ApiResetScript(UUID itemID)
1553 { 1641 {
1554 IScriptInstance instance = GetInstance(itemID); 1642 IScriptInstance instance = GetInstance(itemID);
@@ -1604,6 +1692,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1604 return UUID.Zero; 1692 return UUID.Zero;
1605 } 1693 }
1606 1694
1695 [DebuggerNonUserCode]
1607 public void SetState(UUID itemID, string newState) 1696 public void SetState(UUID itemID, string newState)
1608 { 1697 {
1609 IScriptInstance instance = GetInstance(itemID); 1698 IScriptInstance instance = GetInstance(itemID);
@@ -1626,11 +1715,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1626 1715
1627 List<IScriptInstance> instances = new List<IScriptInstance>(); 1716 List<IScriptInstance> instances = new List<IScriptInstance>();
1628 1717
1629 lock (m_Scripts) 1718 lockScriptsForRead(true);
1630 { 1719 foreach (IScriptInstance instance in m_Scripts.Values)
1631 foreach (IScriptInstance instance in m_Scripts.Values)
1632 instances.Add(instance); 1720 instances.Add(instance);
1633 } 1721 lockScriptsForRead(false);
1634 1722
1635 foreach (IScriptInstance i in instances) 1723 foreach (IScriptInstance i in instances)
1636 { 1724 {