aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/XEngine
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs378
1 files changed, 235 insertions, 143 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 965101a..05ba890 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.Linq; 34using System.Linq;
@@ -129,6 +130,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
129 private Dictionary<UUID, IScriptInstance> m_Scripts = 130 private Dictionary<UUID, IScriptInstance> m_Scripts =
130 new Dictionary<UUID, IScriptInstance>(); 131 new Dictionary<UUID, IScriptInstance>();
131 132
133 private OpenMetaverse.ReaderWriterLockSlim m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
134
132 // Maps the asset ID to the assembly 135 // Maps the asset ID to the assembly
133 136
134 private Dictionary<UUID, string> m_Assemblies = 137 private Dictionary<UUID, string> m_Assemblies =
@@ -151,6 +154,71 @@ namespace OpenSim.Region.ScriptEngine.XEngine
151 IWorkItemResult m_CurrentCompile = null; 154 IWorkItemResult m_CurrentCompile = null;
152 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>(); 155 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>();
153 156
157 private void lockScriptsForRead(bool locked)
158 {
159 if (locked)
160 {
161 if (m_scriptsLock.RecursiveReadCount > 0)
162 {
163 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.");
164 m_scriptsLock.ExitReadLock();
165 }
166 if (m_scriptsLock.RecursiveWriteCount > 0)
167 {
168 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
169 m_scriptsLock.ExitWriteLock();
170 }
171
172 while (!m_scriptsLock.TryEnterReadLock(60000))
173 {
174 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.");
175 if (m_scriptsLock.IsWriteLockHeld)
176 {
177 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
178 }
179 }
180 }
181 else
182 {
183 if (m_scriptsLock.RecursiveReadCount > 0)
184 {
185 m_scriptsLock.ExitReadLock();
186 }
187 }
188 }
189 private void lockScriptsForWrite(bool locked)
190 {
191 if (locked)
192 {
193 if (m_scriptsLock.RecursiveReadCount > 0)
194 {
195 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.");
196 m_scriptsLock.ExitReadLock();
197 }
198 if (m_scriptsLock.RecursiveWriteCount > 0)
199 {
200 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
201 m_scriptsLock.ExitWriteLock();
202 }
203
204 while (!m_scriptsLock.TryEnterWriteLock(60000))
205 {
206 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.");
207 if (m_scriptsLock.IsWriteLockHeld)
208 {
209 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
210 }
211 }
212 }
213 else
214 {
215 if (m_scriptsLock.RecursiveWriteCount > 0)
216 {
217 m_scriptsLock.ExitWriteLock();
218 }
219 }
220 }
221
154 public string ScriptEngineName 222 public string ScriptEngineName
155 { 223 {
156 get { return "XEngine"; } 224 get { return "XEngine"; }
@@ -605,64 +673,69 @@ namespace OpenSim.Region.ScriptEngine.XEngine
605 { 673 {
606 if (!m_Enabled) 674 if (!m_Enabled)
607 return; 675 return;
676 lockScriptsForRead(true);
608 677
609 lock (m_Scripts) 678 List<IScriptInstance> instancesToDel = new List<IScriptInstance>(m_Scripts.Values);
610 {
611 m_log.InfoFormat(
612 "[XEngine]: Shutting down {0} scripts in {1}", m_Scripts.Count, m_Scene.RegionInfo.RegionName);
613 679
614 foreach (IScriptInstance instance in m_Scripts.Values) 680// foreach (IScriptInstance instance in m_Scripts.Values)
681 foreach (IScriptInstance instance in instancesToDel)
682 {
683 // Force a final state save
684 //
685 if (m_Assemblies.ContainsKey(instance.AssetID))
615 { 686 {
616 // Force a final state save 687 string assembly = m_Assemblies[instance.AssetID];
617 //
618 if (m_Assemblies.ContainsKey(instance.AssetID))
619 {
620 string assembly = m_Assemblies[instance.AssetID];
621 688
622 try 689 try
623 { 690 {
624 instance.SaveState(assembly); 691 instance.SaveState(assembly);
625 }
626 catch (Exception e)
627 {
628 m_log.Error(
629 string.Format(
630 "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ",
631 instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name)
632 , e);
633 }
634 } 692 }
693 catch (Exception e)
694 {
695 m_log.Error(
696 string.Format(
697 "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ",
698 instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name)
699 , e);
700 }
701 }
635 702
636 // Clear the event queue and abort the instance thread 703 // Clear the event queue and abort the instance thread
637 // 704 //
638 instance.ClearQueue(); 705 instance.ClearQueue();
639 instance.Stop(0); 706 instance.Stop(0);
640 707
641 // Release events, timer, etc 708 // Release events, timer, etc
642 // 709 //
643 instance.DestroyScriptInstance(); 710 instance.DestroyScriptInstance();
644 711
645 // Unload scripts and app domains. 712 // Unload scripts and app domains
646 // Must be done explicitly because they have infinite 713 // Must be done explicitly because they have infinite
647 // lifetime. 714 // lifetime
648 // However, don't bother to do this if the simulator is shutting 715 //
649 // down since it takes a long time with many scripts. 716// if (!m_SimulatorShuttingDown)
650 if (!m_SimulatorShuttingDown) 717 {
718 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
719 if (m_DomainScripts[instance.AppDomain].Count == 0)
651 { 720 {
652 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 721 m_DomainScripts.Remove(instance.AppDomain);
653 if (m_DomainScripts[instance.AppDomain].Count == 0) 722 UnloadAppDomain(instance.AppDomain);
654 {
655 m_DomainScripts.Remove(instance.AppDomain);
656 UnloadAppDomain(instance.AppDomain);
657 }
658 } 723 }
659 } 724 }
660 725
661 m_Scripts.Clear(); 726// m_Scripts.Clear();
662 m_PrimObjects.Clear(); 727// m_PrimObjects.Clear();
663 m_Assemblies.Clear(); 728// m_Assemblies.Clear();
664 m_DomainScripts.Clear(); 729// m_DomainScripts.Clear();
665 } 730 }
731 lockScriptsForRead(false);
732 lockScriptsForWrite(true);
733 m_Scripts.Clear();
734 lockScriptsForWrite(false);
735 m_PrimObjects.Clear();
736 m_Assemblies.Clear();
737 m_DomainScripts.Clear();
738
666 lock (m_ScriptEngines) 739 lock (m_ScriptEngines)
667 { 740 {
668 m_ScriptEngines.Remove(this); 741 m_ScriptEngines.Remove(this);
@@ -731,22 +804,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
731 804
732 List<IScriptInstance> instances = new List<IScriptInstance>(); 805 List<IScriptInstance> instances = new List<IScriptInstance>();
733 806
734 lock (m_Scripts) 807 lockScriptsForRead(true);
735 { 808 foreach (IScriptInstance instance in m_Scripts.Values)
736 foreach (IScriptInstance instance in m_Scripts.Values)
737 instances.Add(instance); 809 instances.Add(instance);
738 } 810 lockScriptsForRead(false);
739 811
740 foreach (IScriptInstance i in instances) 812 foreach (IScriptInstance i in instances)
741 { 813 {
742 string assembly = String.Empty; 814 string assembly = String.Empty;
743 815
744 lock (m_Scripts) 816
745 {
746 if (!m_Assemblies.ContainsKey(i.AssetID)) 817 if (!m_Assemblies.ContainsKey(i.AssetID))
747 continue; 818 continue;
748 assembly = m_Assemblies[i.AssetID]; 819 assembly = m_Assemblies[i.AssetID];
749 } 820
750 821
751 try 822 try
752 { 823 {
@@ -1147,96 +1218,99 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1147 } 1218 }
1148 1219
1149 ScriptInstance instance = null; 1220 ScriptInstance instance = null;
1150 lock (m_Scripts) 1221 // Create the object record
1222 lockScriptsForRead(true);
1223 if ((!m_Scripts.ContainsKey(itemID)) ||
1224 (m_Scripts[itemID].AssetID != assetID))
1151 { 1225 {
1152 // Create the object record 1226 lockScriptsForRead(false);
1153 if ((!m_Scripts.ContainsKey(itemID)) ||
1154 (m_Scripts[itemID].AssetID != assetID))
1155 {
1156 UUID appDomain = assetID;
1157 1227
1158 if (part.ParentGroup.IsAttachment) 1228 UUID appDomain = assetID;
1159 appDomain = part.ParentGroup.RootPart.UUID;
1160 1229
1161 if (!m_AppDomains.ContainsKey(appDomain)) 1230 if (part.ParentGroup.IsAttachment)
1162 { 1231 appDomain = part.ParentGroup.RootPart.UUID;
1163 try
1164 {
1165 AppDomainSetup appSetup = new AppDomainSetup();
1166 appSetup.PrivateBinPath = Path.Combine(
1167 m_ScriptEnginesPath,
1168 m_Scene.RegionInfo.RegionID.ToString());
1169 1232
1170 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 1233 if (!m_AppDomains.ContainsKey(appDomain))
1171 Evidence evidence = new Evidence(baseEvidence); 1234 {
1235 try
1236 {
1237 AppDomainSetup appSetup = new AppDomainSetup();
1238 appSetup.PrivateBinPath = Path.Combine(
1239 m_ScriptEnginesPath,
1240 m_Scene.RegionInfo.RegionID.ToString());
1172 1241
1173 AppDomain sandbox; 1242 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
1174 if (m_AppDomainLoading) 1243 Evidence evidence = new Evidence(baseEvidence);
1175 {
1176 sandbox = AppDomain.CreateDomain(
1177 m_Scene.RegionInfo.RegionID.ToString(),
1178 evidence, appSetup);
1179 sandbox.AssemblyResolve +=
1180 new ResolveEventHandler(
1181 AssemblyResolver.OnAssemblyResolve);
1182 }
1183 else
1184 {
1185 sandbox = AppDomain.CurrentDomain;
1186 }
1187
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 1244
1198 m_DomainScripts[appDomain] = new List<UUID>(); 1245 AppDomain sandbox;
1246 if (m_AppDomainLoading)
1247 {
1248 sandbox = AppDomain.CreateDomain(
1249 m_Scene.RegionInfo.RegionID.ToString(),
1250 evidence, appSetup);
1251 m_AppDomains[appDomain].AssemblyResolve +=
1252 new ResolveEventHandler(
1253 AssemblyResolver.OnAssemblyResolve);
1199 } 1254 }
1200 catch (Exception e) 1255 else
1201 { 1256 {
1202 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); 1257 sandbox = AppDomain.CurrentDomain;
1203 m_ScriptErrorMessage += "Exception creating app domain:\n";
1204 m_ScriptFailCount++;
1205 lock (m_AddingAssemblies)
1206 {
1207 m_AddingAssemblies[assembly]--;
1208 }
1209 return false;
1210 } 1258 }
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// if (DebugLevel >= 1)
1222// m_log.DebugFormat(
1223// "[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}",
1224// part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
1225// part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1226 1259
1227 if (presence != null) 1260 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1261 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1262 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1263 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1264 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1265 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1266 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1267
1268 m_AppDomains[appDomain] = sandbox;
1269
1270 m_DomainScripts[appDomain] = new List<UUID>();
1271 }
1272 catch (Exception e)
1228 { 1273 {
1229 ShowScriptSaveResponse(item.OwnerID, 1274 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
1230 assetID, "Compile successful", true); 1275 m_ScriptErrorMessage += "Exception creating app domain:\n";
1276 m_ScriptFailCount++;
1277 lock (m_AddingAssemblies)
1278 {
1279 m_AddingAssemblies[assembly]--;
1280 }
1281 return false;
1231 } 1282 }
1283 }
1284 m_DomainScripts[appDomain].Add(itemID);
1285
1286 instance = new ScriptInstance(this, part,
1287 itemID, assetID, assembly,
1288 m_AppDomains[appDomain],
1289 part.ParentGroup.RootPart.Name,
1290 item.Name, startParam, postOnRez,
1291 stateSource, m_MaxScriptQueue);
1292
1293// m_log.DebugFormat(
1294// "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1295// part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
1296// part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1232 1297
1233 instance.AppDomain = appDomain; 1298 if (presence != null)
1234 instance.LineMap = linemap; 1299 {
1235 1300 ShowScriptSaveResponse(item.OwnerID,
1236 m_Scripts[itemID] = instance; 1301 assetID, "Compile successful", true);
1237 } 1302 }
1238 }
1239 1303
1304 instance.AppDomain = appDomain;
1305 instance.LineMap = linemap;
1306 lockScriptsForWrite(true);
1307 m_Scripts[itemID] = instance;
1308 lockScriptsForWrite(false);
1309 }
1310 else
1311 {
1312 lockScriptsForRead(false);
1313 }
1240 lock (m_PrimObjects) 1314 lock (m_PrimObjects)
1241 { 1315 {
1242 if (!m_PrimObjects.ContainsKey(localID)) 1316 if (!m_PrimObjects.ContainsKey(localID))
@@ -1254,7 +1328,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1254 m_AddingAssemblies[assembly]--; 1328 m_AddingAssemblies[assembly]--;
1255 } 1329 }
1256 1330
1257 if (instance != null) 1331 if (instance!=null)
1258 instance.Init(); 1332 instance.Init();
1259 1333
1260 bool runIt; 1334 bool runIt;
@@ -1277,18 +1351,28 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1277 m_CompileDict.Remove(itemID); 1351 m_CompileDict.Remove(itemID);
1278 } 1352 }
1279 1353
1280 IScriptInstance instance = null; 1354 lockScriptsForRead(true);
1281 1355 // Do we even have it?
1282 lock (m_Scripts) 1356 if (!m_Scripts.ContainsKey(itemID))
1283 { 1357 {
1284 // Do we even have it? 1358 // Do we even have it?
1285 if (!m_Scripts.ContainsKey(itemID)) 1359 if (!m_Scripts.ContainsKey(itemID))
1286 return; 1360 return;
1287 1361
1288 instance = m_Scripts[itemID]; 1362 lockScriptsForRead(false);
1363 lockScriptsForWrite(true);
1289 m_Scripts.Remove(itemID); 1364 m_Scripts.Remove(itemID);
1365 lockScriptsForWrite(false);
1366
1367 return;
1290 } 1368 }
1369
1291 1370
1371 IScriptInstance instance=m_Scripts[itemID];
1372 lockScriptsForRead(false);
1373 lockScriptsForWrite(true);
1374 m_Scripts.Remove(itemID);
1375 lockScriptsForWrite(false);
1292 instance.ClearQueue(); 1376 instance.ClearQueue();
1293 1377
1294 // Give the script some time to finish processing its last event. Simply aborting the script thread can 1378 // Give the script some time to finish processing its last event. Simply aborting the script thread can
@@ -1327,8 +1411,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1327 1411
1328 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 1412 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
1329 if (handlerObjectRemoved != null) 1413 if (handlerObjectRemoved != null)
1330 handlerObjectRemoved(instance.ObjectID); 1414 {
1415 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
1416 handlerObjectRemoved(part.UUID);
1417 }
1331 1418
1419 CleanAssemblies();
1420
1332 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 1421 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
1333 if (handlerScriptRemoved != null) 1422 if (handlerScriptRemoved != null)
1334 handlerScriptRemoved(itemID); 1423 handlerScriptRemoved(itemID);
@@ -1588,12 +1677,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1588 private IScriptInstance GetInstance(UUID itemID) 1677 private IScriptInstance GetInstance(UUID itemID)
1589 { 1678 {
1590 IScriptInstance instance; 1679 IScriptInstance instance;
1591 lock (m_Scripts) 1680 lockScriptsForRead(true);
1681 if (!m_Scripts.ContainsKey(itemID))
1592 { 1682 {
1593 if (!m_Scripts.ContainsKey(itemID)) 1683 lockScriptsForRead(false);
1594 return null; 1684 return null;
1595 instance = m_Scripts[itemID];
1596 } 1685 }
1686 instance = m_Scripts[itemID];
1687 lockScriptsForRead(false);
1597 return instance; 1688 return instance;
1598 } 1689 }
1599 1690
@@ -1617,6 +1708,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1617 return false; 1708 return false;
1618 } 1709 }
1619 1710
1711 [DebuggerNonUserCode]
1620 public void ApiResetScript(UUID itemID) 1712 public void ApiResetScript(UUID itemID)
1621 { 1713 {
1622 IScriptInstance instance = GetInstance(itemID); 1714 IScriptInstance instance = GetInstance(itemID);
@@ -1678,6 +1770,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1678 return UUID.Zero; 1770 return UUID.Zero;
1679 } 1771 }
1680 1772
1773 [DebuggerNonUserCode]
1681 public void SetState(UUID itemID, string newState) 1774 public void SetState(UUID itemID, string newState)
1682 { 1775 {
1683 IScriptInstance instance = GetInstance(itemID); 1776 IScriptInstance instance = GetInstance(itemID);
@@ -1700,11 +1793,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1700 1793
1701 List<IScriptInstance> instances = new List<IScriptInstance>(); 1794 List<IScriptInstance> instances = new List<IScriptInstance>();
1702 1795
1703 lock (m_Scripts) 1796 lockScriptsForRead(true);
1704 { 1797 foreach (IScriptInstance instance in m_Scripts.Values)
1705 foreach (IScriptInstance instance in m_Scripts.Values)
1706 instances.Add(instance); 1798 instances.Add(instance);
1707 } 1799 lockScriptsForRead(false);
1708 1800
1709 foreach (IScriptInstance i in instances) 1801 foreach (IScriptInstance i in instances)
1710 { 1802 {