aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-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 06ed9d6..b1583b2 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 }
@@ -1048,96 +1115,99 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1048 } 1115 }
1049 1116
1050 ScriptInstance instance = null; 1117 ScriptInstance instance = null;
1051 lock (m_Scripts) 1118 // Create the object record
1119 lockScriptsForRead(true);
1120 if ((!m_Scripts.ContainsKey(itemID)) ||
1121 (m_Scripts[itemID].AssetID != assetID))
1052 { 1122 {
1053 // Create the object record 1123 lockScriptsForRead(false);
1054 if ((!m_Scripts.ContainsKey(itemID)) ||
1055 (m_Scripts[itemID].AssetID != assetID))
1056 {
1057 UUID appDomain = assetID;
1058 1124
1059 if (part.ParentGroup.IsAttachment) 1125 UUID appDomain = assetID;
1060 appDomain = part.ParentGroup.RootPart.UUID;
1061 1126
1062 if (!m_AppDomains.ContainsKey(appDomain)) 1127 if (part.ParentGroup.IsAttachment)
1063 { 1128 appDomain = part.ParentGroup.RootPart.UUID;
1064 try
1065 {
1066 AppDomainSetup appSetup = new AppDomainSetup();
1067 appSetup.PrivateBinPath = Path.Combine(
1068 m_ScriptEnginesPath,
1069 m_Scene.RegionInfo.RegionID.ToString());
1070 1129
1071 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 1130 if (!m_AppDomains.ContainsKey(appDomain))
1072 Evidence evidence = new Evidence(baseEvidence); 1131 {
1132 try
1133 {
1134 AppDomainSetup appSetup = new AppDomainSetup();
1135 appSetup.PrivateBinPath = Path.Combine(
1136 m_ScriptEnginesPath,
1137 m_Scene.RegionInfo.RegionID.ToString());
1073 1138
1074 AppDomain sandbox; 1139 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
1075 if (m_AppDomainLoading) 1140 Evidence evidence = new Evidence(baseEvidence);
1076 {
1077 sandbox = AppDomain.CreateDomain(
1078 m_Scene.RegionInfo.RegionID.ToString(),
1079 evidence, appSetup);
1080 sandbox.AssemblyResolve +=
1081 new ResolveEventHandler(
1082 AssemblyResolver.OnAssemblyResolve);
1083 }
1084 else
1085 {
1086 sandbox = AppDomain.CurrentDomain;
1087 }
1088
1089 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1090 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1091 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1092 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1093 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1094 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1095 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1096
1097 m_AppDomains[appDomain] = sandbox;
1098 1141
1099 m_DomainScripts[appDomain] = new List<UUID>(); 1142 AppDomain sandbox;
1143 if (m_AppDomainLoading)
1144 {
1145 sandbox = AppDomain.CreateDomain(
1146 m_Scene.RegionInfo.RegionID.ToString(),
1147 evidence, appSetup);
1148 m_AppDomains[appDomain].AssemblyResolve +=
1149 new ResolveEventHandler(
1150 AssemblyResolver.OnAssemblyResolve);
1100 } 1151 }
1101 catch (Exception e) 1152 else
1102 { 1153 {
1103 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); 1154 sandbox = AppDomain.CurrentDomain;
1104 m_ScriptErrorMessage += "Exception creating app domain:\n";
1105 m_ScriptFailCount++;
1106 lock (m_AddingAssemblies)
1107 {
1108 m_AddingAssemblies[assembly]--;
1109 }
1110 return false;
1111 } 1155 }
1112 }
1113 m_DomainScripts[appDomain].Add(itemID);
1114
1115 instance = new ScriptInstance(this, part,
1116 itemID, assetID, assembly,
1117 m_AppDomains[appDomain],
1118 part.ParentGroup.RootPart.Name,
1119 item.Name, startParam, postOnRez,
1120 stateSource, m_MaxScriptQueue);
1121
1122// if (DebugLevel >= 1)
1123 m_log.DebugFormat(
1124 "[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}",
1125 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID,
1126 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1127 1156
1128 if (presence != null) 1157 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1158 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1159 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1160 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1161 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1162 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1163 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1164
1165 m_AppDomains[appDomain] = sandbox;
1166
1167 m_DomainScripts[appDomain] = new List<UUID>();
1168 }
1169 catch (Exception e)
1129 { 1170 {
1130 ShowScriptSaveResponse(item.OwnerID, 1171 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
1131 assetID, "Compile successful", true); 1172 m_ScriptErrorMessage += "Exception creating app domain:\n";
1173 m_ScriptFailCount++;
1174 lock (m_AddingAssemblies)
1175 {
1176 m_AddingAssemblies[assembly]--;
1177 }
1178 return false;
1132 } 1179 }
1180 }
1181 m_DomainScripts[appDomain].Add(itemID);
1182
1183 instance = new ScriptInstance(this, part,
1184 itemID, assetID, assembly,
1185 m_AppDomains[appDomain],
1186 part.ParentGroup.RootPart.Name,
1187 item.Name, startParam, postOnRez,
1188 stateSource, m_MaxScriptQueue);
1189
1190 m_log.DebugFormat(
1191 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1192 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
1193 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1133 1194
1134 instance.AppDomain = appDomain; 1195 if (presence != null)
1135 instance.LineMap = linemap; 1196 {
1136 1197 ShowScriptSaveResponse(item.OwnerID,
1137 m_Scripts[itemID] = instance; 1198 assetID, "Compile successful", true);
1138 } 1199 }
1139 }
1140 1200
1201 instance.AppDomain = appDomain;
1202 instance.LineMap = linemap;
1203 lockScriptsForWrite(true);
1204 m_Scripts[itemID] = instance;
1205 lockScriptsForWrite(false);
1206 }
1207 else
1208 {
1209 lockScriptsForRead(false);
1210 }
1141 lock (m_PrimObjects) 1211 lock (m_PrimObjects)
1142 { 1212 {
1143 if (!m_PrimObjects.ContainsKey(localID)) 1213 if (!m_PrimObjects.ContainsKey(localID))
@@ -1155,9 +1225,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1155 m_AddingAssemblies[assembly]--; 1225 m_AddingAssemblies[assembly]--;
1156 } 1226 }
1157 1227
1158 if (instance != null) 1228 if (instance!=null)
1159 instance.Init(); 1229 instance.Init();
1160 1230
1161 return true; 1231 return true;
1162 } 1232 }
1163 1233
@@ -1170,18 +1240,28 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1170 m_CompileDict.Remove(itemID); 1240 m_CompileDict.Remove(itemID);
1171 } 1241 }
1172 1242
1173 IScriptInstance instance = null; 1243 lockScriptsForRead(true);
1174 1244 // Do we even have it?
1175 lock (m_Scripts) 1245 if (!m_Scripts.ContainsKey(itemID))
1176 { 1246 {
1177 // Do we even have it? 1247 // Do we even have it?
1178 if (!m_Scripts.ContainsKey(itemID)) 1248 if (!m_Scripts.ContainsKey(itemID))
1179 return; 1249 return;
1180 1250
1181 instance = m_Scripts[itemID]; 1251 lockScriptsForRead(false);
1252 lockScriptsForWrite(true);
1182 m_Scripts.Remove(itemID); 1253 m_Scripts.Remove(itemID);
1254 lockScriptsForWrite(false);
1255
1256 return;
1183 } 1257 }
1258
1184 1259
1260 IScriptInstance instance=m_Scripts[itemID];
1261 lockScriptsForRead(false);
1262 lockScriptsForWrite(true);
1263 m_Scripts.Remove(itemID);
1264 lockScriptsForWrite(false);
1185 instance.ClearQueue(); 1265 instance.ClearQueue();
1186 1266
1187 // Give the script some time to finish processing its last event. Simply aborting the script thread can 1267 // Give the script some time to finish processing its last event. Simply aborting the script thread can
@@ -1220,8 +1300,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1220 1300
1221 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 1301 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
1222 if (handlerObjectRemoved != null) 1302 if (handlerObjectRemoved != null)
1223 handlerObjectRemoved(instance.ObjectID); 1303 {
1304 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
1305 handlerObjectRemoved(part.UUID);
1306 }
1224 1307
1308 CleanAssemblies();
1309
1225 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 1310 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
1226 if (handlerScriptRemoved != null) 1311 if (handlerScriptRemoved != null)
1227 handlerScriptRemoved(itemID); 1312 handlerScriptRemoved(itemID);
@@ -1482,12 +1567,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1482 private IScriptInstance GetInstance(UUID itemID) 1567 private IScriptInstance GetInstance(UUID itemID)
1483 { 1568 {
1484 IScriptInstance instance; 1569 IScriptInstance instance;
1485 lock (m_Scripts) 1570 lockScriptsForRead(true);
1571 if (!m_Scripts.ContainsKey(itemID))
1486 { 1572 {
1487 if (!m_Scripts.ContainsKey(itemID)) 1573 lockScriptsForRead(false);
1488 return null; 1574 return null;
1489 instance = m_Scripts[itemID];
1490 } 1575 }
1576 instance = m_Scripts[itemID];
1577 lockScriptsForRead(false);
1491 return instance; 1578 return instance;
1492 } 1579 }
1493 1580
@@ -1518,6 +1605,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1518 return false; 1605 return false;
1519 } 1606 }
1520 1607
1608 [DebuggerNonUserCode]
1521 public void ApiResetScript(UUID itemID) 1609 public void ApiResetScript(UUID itemID)
1522 { 1610 {
1523 IScriptInstance instance = GetInstance(itemID); 1611 IScriptInstance instance = GetInstance(itemID);
@@ -1569,6 +1657,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1569 return UUID.Zero; 1657 return UUID.Zero;
1570 } 1658 }
1571 1659
1660 [DebuggerNonUserCode]
1572 public void SetState(UUID itemID, string newState) 1661 public void SetState(UUID itemID, string newState)
1573 { 1662 {
1574 IScriptInstance instance = GetInstance(itemID); 1663 IScriptInstance instance = GetInstance(itemID);
@@ -1591,11 +1680,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1591 1680
1592 List<IScriptInstance> instances = new List<IScriptInstance>(); 1681 List<IScriptInstance> instances = new List<IScriptInstance>();
1593 1682
1594 lock (m_Scripts) 1683 lockScriptsForRead(true);
1595 { 1684 foreach (IScriptInstance instance in m_Scripts.Values)
1596 foreach (IScriptInstance instance in m_Scripts.Values)
1597 instances.Add(instance); 1685 instances.Add(instance);
1598 } 1686 lockScriptsForRead(false);
1599 1687
1600 foreach (IScriptInstance i in instances) 1688 foreach (IScriptInstance i in instances)
1601 { 1689 {
@@ -2050,5 +2138,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine
2050// else 2138// else
2051// m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID); 2139// m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID);
2052 } 2140 }
2141
2142 public bool HasScript(UUID itemID, out bool running)
2143 {
2144 running = true;
2145
2146 IScriptInstance instance = GetInstance(itemID);
2147 if (instance == null)
2148 return false;
2149
2150 running = instance.Running;
2151 return true;
2152 }
2053 } 2153 }
2054} 2154}