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.cs360
1 files changed, 230 insertions, 130 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index a709be3..79d1944 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 }
@@ -1072,96 +1139,99 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1072 } 1139 }
1073 1140
1074 ScriptInstance instance = null; 1141 ScriptInstance instance = null;
1075 lock (m_Scripts) 1142 // Create the object record
1143 lockScriptsForRead(true);
1144 if ((!m_Scripts.ContainsKey(itemID)) ||
1145 (m_Scripts[itemID].AssetID != assetID))
1076 { 1146 {
1077 // Create the object record 1147 lockScriptsForRead(false);
1078 if ((!m_Scripts.ContainsKey(itemID)) ||
1079 (m_Scripts[itemID].AssetID != assetID))
1080 {
1081 UUID appDomain = assetID;
1082 1148
1083 if (part.ParentGroup.IsAttachment) 1149 UUID appDomain = assetID;
1084 appDomain = part.ParentGroup.RootPart.UUID;
1085 1150
1086 if (!m_AppDomains.ContainsKey(appDomain)) 1151 if (part.ParentGroup.IsAttachment)
1087 { 1152 appDomain = part.ParentGroup.RootPart.UUID;
1088 try
1089 {
1090 AppDomainSetup appSetup = new AppDomainSetup();
1091 appSetup.PrivateBinPath = Path.Combine(
1092 m_ScriptEnginesPath,
1093 m_Scene.RegionInfo.RegionID.ToString());
1094 1153
1095 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 1154 if (!m_AppDomains.ContainsKey(appDomain))
1096 Evidence evidence = new Evidence(baseEvidence); 1155 {
1156 try
1157 {
1158 AppDomainSetup appSetup = new AppDomainSetup();
1159 appSetup.PrivateBinPath = Path.Combine(
1160 m_ScriptEnginesPath,
1161 m_Scene.RegionInfo.RegionID.ToString());
1097 1162
1098 AppDomain sandbox; 1163 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
1099 if (m_AppDomainLoading) 1164 Evidence evidence = new Evidence(baseEvidence);
1100 {
1101 sandbox = AppDomain.CreateDomain(
1102 m_Scene.RegionInfo.RegionID.ToString(),
1103 evidence, appSetup);
1104 sandbox.AssemblyResolve +=
1105 new ResolveEventHandler(
1106 AssemblyResolver.OnAssemblyResolve);
1107 }
1108 else
1109 {
1110 sandbox = AppDomain.CurrentDomain;
1111 }
1112
1113 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1114 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1115 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1116 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1117 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1118 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1119 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1120
1121 m_AppDomains[appDomain] = sandbox;
1122 1165
1123 m_DomainScripts[appDomain] = new List<UUID>(); 1166 AppDomain sandbox;
1167 if (m_AppDomainLoading)
1168 {
1169 sandbox = AppDomain.CreateDomain(
1170 m_Scene.RegionInfo.RegionID.ToString(),
1171 evidence, appSetup);
1172 m_AppDomains[appDomain].AssemblyResolve +=
1173 new ResolveEventHandler(
1174 AssemblyResolver.OnAssemblyResolve);
1124 } 1175 }
1125 catch (Exception e) 1176 else
1126 { 1177 {
1127 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); 1178 sandbox = AppDomain.CurrentDomain;
1128 m_ScriptErrorMessage += "Exception creating app domain:\n";
1129 m_ScriptFailCount++;
1130 lock (m_AddingAssemblies)
1131 {
1132 m_AddingAssemblies[assembly]--;
1133 }
1134 return false;
1135 } 1179 }
1136 }
1137 m_DomainScripts[appDomain].Add(itemID);
1138
1139 instance = new ScriptInstance(this, part,
1140 itemID, assetID, assembly,
1141 m_AppDomains[appDomain],
1142 part.ParentGroup.RootPart.Name,
1143 item.Name, startParam, postOnRez,
1144 stateSource, m_MaxScriptQueue);
1145
1146// if (DebugLevel >= 1)
1147 m_log.DebugFormat(
1148 "[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}",
1149 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
1150 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1151 1180
1152 if (presence != null) 1181 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1182 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1183 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1184 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1185 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1186 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1187 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1188
1189 m_AppDomains[appDomain] = sandbox;
1190
1191 m_DomainScripts[appDomain] = new List<UUID>();
1192 }
1193 catch (Exception e)
1153 { 1194 {
1154 ShowScriptSaveResponse(item.OwnerID, 1195 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
1155 assetID, "Compile successful", true); 1196 m_ScriptErrorMessage += "Exception creating app domain:\n";
1197 m_ScriptFailCount++;
1198 lock (m_AddingAssemblies)
1199 {
1200 m_AddingAssemblies[assembly]--;
1201 }
1202 return false;
1156 } 1203 }
1204 }
1205 m_DomainScripts[appDomain].Add(itemID);
1206
1207 instance = new ScriptInstance(this, part,
1208 itemID, assetID, assembly,
1209 m_AppDomains[appDomain],
1210 part.ParentGroup.RootPart.Name,
1211 item.Name, startParam, postOnRez,
1212 stateSource, m_MaxScriptQueue);
1213
1214 m_log.DebugFormat(
1215 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1216 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
1217 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1157 1218
1158 instance.AppDomain = appDomain; 1219 if (presence != null)
1159 instance.LineMap = linemap; 1220 {
1160 1221 ShowScriptSaveResponse(item.OwnerID,
1161 m_Scripts[itemID] = instance; 1222 assetID, "Compile successful", true);
1162 } 1223 }
1163 }
1164 1224
1225 instance.AppDomain = appDomain;
1226 instance.LineMap = linemap;
1227 lockScriptsForWrite(true);
1228 m_Scripts[itemID] = instance;
1229 lockScriptsForWrite(false);
1230 }
1231 else
1232 {
1233 lockScriptsForRead(false);
1234 }
1165 lock (m_PrimObjects) 1235 lock (m_PrimObjects)
1166 { 1236 {
1167 if (!m_PrimObjects.ContainsKey(localID)) 1237 if (!m_PrimObjects.ContainsKey(localID))
@@ -1179,9 +1249,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1179 m_AddingAssemblies[assembly]--; 1249 m_AddingAssemblies[assembly]--;
1180 } 1250 }
1181 1251
1182 if (instance != null) 1252 if (instance!=null)
1183 instance.Init(); 1253 instance.Init();
1184 1254
1185 return true; 1255 return true;
1186 } 1256 }
1187 1257
@@ -1194,18 +1264,28 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1194 m_CompileDict.Remove(itemID); 1264 m_CompileDict.Remove(itemID);
1195 } 1265 }
1196 1266
1197 IScriptInstance instance = null; 1267 lockScriptsForRead(true);
1198 1268 // Do we even have it?
1199 lock (m_Scripts) 1269 if (!m_Scripts.ContainsKey(itemID))
1200 { 1270 {
1201 // Do we even have it? 1271 // Do we even have it?
1202 if (!m_Scripts.ContainsKey(itemID)) 1272 if (!m_Scripts.ContainsKey(itemID))
1203 return; 1273 return;
1204 1274
1205 instance = m_Scripts[itemID]; 1275 lockScriptsForRead(false);
1276 lockScriptsForWrite(true);
1206 m_Scripts.Remove(itemID); 1277 m_Scripts.Remove(itemID);
1278 lockScriptsForWrite(false);
1279
1280 return;
1207 } 1281 }
1282
1208 1283
1284 IScriptInstance instance=m_Scripts[itemID];
1285 lockScriptsForRead(false);
1286 lockScriptsForWrite(true);
1287 m_Scripts.Remove(itemID);
1288 lockScriptsForWrite(false);
1209 instance.ClearQueue(); 1289 instance.ClearQueue();
1210 1290
1211 // Give the script some time to finish processing its last event. Simply aborting the script thread can 1291 // Give the script some time to finish processing its last event. Simply aborting the script thread can
@@ -1244,8 +1324,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1244 1324
1245 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 1325 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
1246 if (handlerObjectRemoved != null) 1326 if (handlerObjectRemoved != null)
1247 handlerObjectRemoved(instance.ObjectID); 1327 {
1328 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
1329 handlerObjectRemoved(part.UUID);
1330 }
1248 1331
1332 CleanAssemblies();
1333
1249 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 1334 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
1250 if (handlerScriptRemoved != null) 1335 if (handlerScriptRemoved != null)
1251 handlerScriptRemoved(itemID); 1336 handlerScriptRemoved(itemID);
@@ -1506,12 +1591,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1506 private IScriptInstance GetInstance(UUID itemID) 1591 private IScriptInstance GetInstance(UUID itemID)
1507 { 1592 {
1508 IScriptInstance instance; 1593 IScriptInstance instance;
1509 lock (m_Scripts) 1594 lockScriptsForRead(true);
1595 if (!m_Scripts.ContainsKey(itemID))
1510 { 1596 {
1511 if (!m_Scripts.ContainsKey(itemID)) 1597 lockScriptsForRead(false);
1512 return null; 1598 return null;
1513 instance = m_Scripts[itemID];
1514 } 1599 }
1600 instance = m_Scripts[itemID];
1601 lockScriptsForRead(false);
1515 return instance; 1602 return instance;
1516 } 1603 }
1517 1604
@@ -1542,6 +1629,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1542 return false; 1629 return false;
1543 } 1630 }
1544 1631
1632 [DebuggerNonUserCode]
1545 public void ApiResetScript(UUID itemID) 1633 public void ApiResetScript(UUID itemID)
1546 { 1634 {
1547 IScriptInstance instance = GetInstance(itemID); 1635 IScriptInstance instance = GetInstance(itemID);
@@ -1593,6 +1681,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1593 return UUID.Zero; 1681 return UUID.Zero;
1594 } 1682 }
1595 1683
1684 [DebuggerNonUserCode]
1596 public void SetState(UUID itemID, string newState) 1685 public void SetState(UUID itemID, string newState)
1597 { 1686 {
1598 IScriptInstance instance = GetInstance(itemID); 1687 IScriptInstance instance = GetInstance(itemID);
@@ -1615,11 +1704,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1615 1704
1616 List<IScriptInstance> instances = new List<IScriptInstance>(); 1705 List<IScriptInstance> instances = new List<IScriptInstance>();
1617 1706
1618 lock (m_Scripts) 1707 lockScriptsForRead(true);
1619 { 1708 foreach (IScriptInstance instance in m_Scripts.Values)
1620 foreach (IScriptInstance instance in m_Scripts.Values)
1621 instances.Add(instance); 1709 instances.Add(instance);
1622 } 1710 lockScriptsForRead(false);
1623 1711
1624 foreach (IScriptInstance i in instances) 1712 foreach (IScriptInstance i in instances)
1625 { 1713 {
@@ -2074,5 +2162,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine
2074// else 2162// else
2075// m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID); 2163// m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID);
2076 } 2164 }
2165
2166 public bool HasScript(UUID itemID, out bool running)
2167 {
2168 running = true;
2169
2170 IScriptInstance instance = GetInstance(itemID);
2171 if (instance == null)
2172 return false;
2173
2174 running = instance.Running;
2175 return true;
2176 }
2077 } 2177 }
2078} 2178}