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.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 5a3f002..2d17977 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,64 +644,69 @@ 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 //
589 if (m_Assemblies.ContainsKey(instance.AssetID))
590 {
591 string assembly = m_Assemblies[instance.AssetID];
592 659
593 try 660 try
594 { 661 {
595 instance.SaveState(assembly); 662 instance.SaveState(assembly);
596 }
597 catch (Exception e)
598 {
599 m_log.Error(
600 string.Format(
601 "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ",
602 instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name)
603 , e);
604 }
605 } 663 }
664 catch (Exception e)
665 {
666 m_log.Error(
667 string.Format(
668 "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ",
669 instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name)
670 , e);
671 }
672 }
606 673
607 // Clear the event queue and abort the instance thread 674 // Clear the event queue and abort the instance thread
608 // 675 //
609 instance.ClearQueue(); 676 instance.ClearQueue();
610 instance.Stop(0); 677 instance.Stop(0);
611 678
612 // Release events, timer, etc 679 // Release events, timer, etc
613 // 680 //
614 instance.DestroyScriptInstance(); 681 instance.DestroyScriptInstance();
615 682
616 // Unload scripts and app domains. 683 // Unload scripts and app domains
617 // Must be done explicitly because they have infinite 684 // Must be done explicitly because they have infinite
618 // lifetime. 685 // lifetime
619 // However, don't bother to do this if the simulator is shutting 686 //
620 // down since it takes a long time with many scripts. 687// if (!m_SimulatorShuttingDown)
621 if (!m_SimulatorShuttingDown) 688 {
689 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
690 if (m_DomainScripts[instance.AppDomain].Count == 0)
622 { 691 {
623 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 692 m_DomainScripts.Remove(instance.AppDomain);
624 if (m_DomainScripts[instance.AppDomain].Count == 0) 693 UnloadAppDomain(instance.AppDomain);
625 {
626 m_DomainScripts.Remove(instance.AppDomain);
627 UnloadAppDomain(instance.AppDomain);
628 }
629 } 694 }
630 } 695 }
631 696
632 m_Scripts.Clear(); 697// m_Scripts.Clear();
633 m_PrimObjects.Clear(); 698// m_PrimObjects.Clear();
634 m_Assemblies.Clear(); 699// m_Assemblies.Clear();
635 m_DomainScripts.Clear(); 700// m_DomainScripts.Clear();
636 } 701 }
702 lockScriptsForRead(false);
703 lockScriptsForWrite(true);
704 m_Scripts.Clear();
705 lockScriptsForWrite(false);
706 m_PrimObjects.Clear();
707 m_Assemblies.Clear();
708 m_DomainScripts.Clear();
709
637 lock (m_ScriptEngines) 710 lock (m_ScriptEngines)
638 { 711 {
639 m_ScriptEngines.Remove(this); 712 m_ScriptEngines.Remove(this);
@@ -702,22 +775,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
702 775
703 List<IScriptInstance> instances = new List<IScriptInstance>(); 776 List<IScriptInstance> instances = new List<IScriptInstance>();
704 777
705 lock (m_Scripts) 778 lockScriptsForRead(true);
706 { 779 foreach (IScriptInstance instance in m_Scripts.Values)
707 foreach (IScriptInstance instance in m_Scripts.Values)
708 instances.Add(instance); 780 instances.Add(instance);
709 } 781 lockScriptsForRead(false);
710 782
711 foreach (IScriptInstance i in instances) 783 foreach (IScriptInstance i in instances)
712 { 784 {
713 string assembly = String.Empty; 785 string assembly = String.Empty;
714 786
715 lock (m_Scripts) 787
716 {
717 if (!m_Assemblies.ContainsKey(i.AssetID)) 788 if (!m_Assemblies.ContainsKey(i.AssetID))
718 continue; 789 continue;
719 assembly = m_Assemblies[i.AssetID]; 790 assembly = m_Assemblies[i.AssetID];
720 } 791
721 792
722 try 793 try
723 { 794 {
@@ -1117,96 +1188,99 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1117 } 1188 }
1118 1189
1119 ScriptInstance instance = null; 1190 ScriptInstance instance = null;
1120 lock (m_Scripts) 1191 // Create the object record
1192 lockScriptsForRead(true);
1193 if ((!m_Scripts.ContainsKey(itemID)) ||
1194 (m_Scripts[itemID].AssetID != assetID))
1121 { 1195 {
1122 // Create the object record 1196 lockScriptsForRead(false);
1123 if ((!m_Scripts.ContainsKey(itemID)) ||
1124 (m_Scripts[itemID].AssetID != assetID))
1125 {
1126 UUID appDomain = assetID;
1127 1197
1128 if (part.ParentGroup.IsAttachment) 1198 UUID appDomain = assetID;
1129 appDomain = part.ParentGroup.RootPart.UUID;
1130 1199
1131 if (!m_AppDomains.ContainsKey(appDomain)) 1200 if (part.ParentGroup.IsAttachment)
1132 { 1201 appDomain = part.ParentGroup.RootPart.UUID;
1133 try
1134 {
1135 AppDomainSetup appSetup = new AppDomainSetup();
1136 appSetup.PrivateBinPath = Path.Combine(
1137 m_ScriptEnginesPath,
1138 m_Scene.RegionInfo.RegionID.ToString());
1139 1202
1140 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 1203 if (!m_AppDomains.ContainsKey(appDomain))
1141 Evidence evidence = new Evidence(baseEvidence); 1204 {
1205 try
1206 {
1207 AppDomainSetup appSetup = new AppDomainSetup();
1208 appSetup.PrivateBinPath = Path.Combine(
1209 m_ScriptEnginesPath,
1210 m_Scene.RegionInfo.RegionID.ToString());
1142 1211
1143 AppDomain sandbox; 1212 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
1144 if (m_AppDomainLoading) 1213 Evidence evidence = new Evidence(baseEvidence);
1145 {
1146 sandbox = AppDomain.CreateDomain(
1147 m_Scene.RegionInfo.RegionID.ToString(),
1148 evidence, appSetup);
1149 sandbox.AssemblyResolve +=
1150 new ResolveEventHandler(
1151 AssemblyResolver.OnAssemblyResolve);
1152 }
1153 else
1154 {
1155 sandbox = AppDomain.CurrentDomain;
1156 }
1157
1158 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1159 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1160 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1161 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1162 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1163 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1164 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1165
1166 m_AppDomains[appDomain] = sandbox;
1167 1214
1168 m_DomainScripts[appDomain] = new List<UUID>(); 1215 AppDomain sandbox;
1216 if (m_AppDomainLoading)
1217 {
1218 sandbox = AppDomain.CreateDomain(
1219 m_Scene.RegionInfo.RegionID.ToString(),
1220 evidence, appSetup);
1221 m_AppDomains[appDomain].AssemblyResolve +=
1222 new ResolveEventHandler(
1223 AssemblyResolver.OnAssemblyResolve);
1169 } 1224 }
1170 catch (Exception e) 1225 else
1171 { 1226 {
1172 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); 1227 sandbox = AppDomain.CurrentDomain;
1173 m_ScriptErrorMessage += "Exception creating app domain:\n";
1174 m_ScriptFailCount++;
1175 lock (m_AddingAssemblies)
1176 {
1177 m_AddingAssemblies[assembly]--;
1178 }
1179 return false;
1180 } 1228 }
1181 }
1182 m_DomainScripts[appDomain].Add(itemID);
1183
1184 instance = new ScriptInstance(this, part,
1185 itemID, assetID, assembly,
1186 m_AppDomains[appDomain],
1187 part.ParentGroup.RootPart.Name,
1188 item.Name, startParam, postOnRez,
1189 stateSource, m_MaxScriptQueue);
1190
1191// if (DebugLevel >= 1)
1192// m_log.DebugFormat(
1193// "[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}",
1194// part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
1195// part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1196 1229
1197 if (presence != null) 1230 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1231 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1232 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1233 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1234 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1235 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1236 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1237
1238 m_AppDomains[appDomain] = sandbox;
1239
1240 m_DomainScripts[appDomain] = new List<UUID>();
1241 }
1242 catch (Exception e)
1198 { 1243 {
1199 ShowScriptSaveResponse(item.OwnerID, 1244 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
1200 assetID, "Compile successful", true); 1245 m_ScriptErrorMessage += "Exception creating app domain:\n";
1246 m_ScriptFailCount++;
1247 lock (m_AddingAssemblies)
1248 {
1249 m_AddingAssemblies[assembly]--;
1250 }
1251 return false;
1201 } 1252 }
1253 }
1254 m_DomainScripts[appDomain].Add(itemID);
1255
1256 instance = new ScriptInstance(this, part,
1257 itemID, assetID, assembly,
1258 m_AppDomains[appDomain],
1259 part.ParentGroup.RootPart.Name,
1260 item.Name, startParam, postOnRez,
1261 stateSource, m_MaxScriptQueue);
1262
1263// m_log.DebugFormat(
1264// "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1265// part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
1266// part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1202 1267
1203 instance.AppDomain = appDomain; 1268 if (presence != null)
1204 instance.LineMap = linemap; 1269 {
1205 1270 ShowScriptSaveResponse(item.OwnerID,
1206 m_Scripts[itemID] = instance; 1271 assetID, "Compile successful", true);
1207 } 1272 }
1208 }
1209 1273
1274 instance.AppDomain = appDomain;
1275 instance.LineMap = linemap;
1276 lockScriptsForWrite(true);
1277 m_Scripts[itemID] = instance;
1278 lockScriptsForWrite(false);
1279 }
1280 else
1281 {
1282 lockScriptsForRead(false);
1283 }
1210 lock (m_PrimObjects) 1284 lock (m_PrimObjects)
1211 { 1285 {
1212 if (!m_PrimObjects.ContainsKey(localID)) 1286 if (!m_PrimObjects.ContainsKey(localID))
@@ -1224,7 +1298,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1224 m_AddingAssemblies[assembly]--; 1298 m_AddingAssemblies[assembly]--;
1225 } 1299 }
1226 1300
1227 if (instance != null) 1301 if (instance!=null)
1228 instance.Init(); 1302 instance.Init();
1229 1303
1230 bool runIt; 1304 bool runIt;
@@ -1247,18 +1321,28 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1247 m_CompileDict.Remove(itemID); 1321 m_CompileDict.Remove(itemID);
1248 } 1322 }
1249 1323
1250 IScriptInstance instance = null; 1324 lockScriptsForRead(true);
1251 1325 // Do we even have it?
1252 lock (m_Scripts) 1326 if (!m_Scripts.ContainsKey(itemID))
1253 { 1327 {
1254 // Do we even have it? 1328 // Do we even have it?
1255 if (!m_Scripts.ContainsKey(itemID)) 1329 if (!m_Scripts.ContainsKey(itemID))
1256 return; 1330 return;
1257 1331
1258 instance = m_Scripts[itemID]; 1332 lockScriptsForRead(false);
1333 lockScriptsForWrite(true);
1259 m_Scripts.Remove(itemID); 1334 m_Scripts.Remove(itemID);
1335 lockScriptsForWrite(false);
1336
1337 return;
1260 } 1338 }
1339
1261 1340
1341 IScriptInstance instance=m_Scripts[itemID];
1342 lockScriptsForRead(false);
1343 lockScriptsForWrite(true);
1344 m_Scripts.Remove(itemID);
1345 lockScriptsForWrite(false);
1262 instance.ClearQueue(); 1346 instance.ClearQueue();
1263 1347
1264 // Give the script some time to finish processing its last event. Simply aborting the script thread can 1348 // Give the script some time to finish processing its last event. Simply aborting the script thread can
@@ -1297,8 +1381,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1297 1381
1298 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 1382 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
1299 if (handlerObjectRemoved != null) 1383 if (handlerObjectRemoved != null)
1300 handlerObjectRemoved(instance.ObjectID); 1384 {
1385 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
1386 handlerObjectRemoved(part.UUID);
1387 }
1301 1388
1389 CleanAssemblies();
1390
1302 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 1391 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
1303 if (handlerScriptRemoved != null) 1392 if (handlerScriptRemoved != null)
1304 handlerScriptRemoved(itemID); 1393 handlerScriptRemoved(itemID);
@@ -1559,12 +1648,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1559 private IScriptInstance GetInstance(UUID itemID) 1648 private IScriptInstance GetInstance(UUID itemID)
1560 { 1649 {
1561 IScriptInstance instance; 1650 IScriptInstance instance;
1562 lock (m_Scripts) 1651 lockScriptsForRead(true);
1652 if (!m_Scripts.ContainsKey(itemID))
1563 { 1653 {
1564 if (!m_Scripts.ContainsKey(itemID)) 1654 lockScriptsForRead(false);
1565 return null; 1655 return null;
1566 instance = m_Scripts[itemID];
1567 } 1656 }
1657 instance = m_Scripts[itemID];
1658 lockScriptsForRead(false);
1568 return instance; 1659 return instance;
1569 } 1660 }
1570 1661
@@ -1588,6 +1679,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1588 return false; 1679 return false;
1589 } 1680 }
1590 1681
1682 [DebuggerNonUserCode]
1591 public void ApiResetScript(UUID itemID) 1683 public void ApiResetScript(UUID itemID)
1592 { 1684 {
1593 IScriptInstance instance = GetInstance(itemID); 1685 IScriptInstance instance = GetInstance(itemID);
@@ -1649,6 +1741,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1649 return UUID.Zero; 1741 return UUID.Zero;
1650 } 1742 }
1651 1743
1744 [DebuggerNonUserCode]
1652 public void SetState(UUID itemID, string newState) 1745 public void SetState(UUID itemID, string newState)
1653 { 1746 {
1654 IScriptInstance instance = GetInstance(itemID); 1747 IScriptInstance instance = GetInstance(itemID);
@@ -1671,11 +1764,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1671 1764
1672 List<IScriptInstance> instances = new List<IScriptInstance>(); 1765 List<IScriptInstance> instances = new List<IScriptInstance>();
1673 1766
1674 lock (m_Scripts) 1767 lockScriptsForRead(true);
1675 { 1768 foreach (IScriptInstance instance in m_Scripts.Values)
1676 foreach (IScriptInstance instance in m_Scripts.Values)
1677 instances.Add(instance); 1769 instances.Add(instance);
1678 } 1770 lockScriptsForRead(false);
1679 1771
1680 foreach (IScriptInstance i in instances) 1772 foreach (IScriptInstance i in instances)
1681 { 1773 {