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.cs364
1 files changed, 233 insertions, 131 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 7712076..1e0f01f 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;
@@ -112,6 +113,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
112 private Dictionary<UUID, IScriptInstance> m_Scripts = 113 private Dictionary<UUID, IScriptInstance> m_Scripts =
113 new Dictionary<UUID, IScriptInstance>(); 114 new Dictionary<UUID, IScriptInstance>();
114 115
116 private OpenMetaverse.ReaderWriterLockSlim m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
117
115 // Maps the asset ID to the assembly 118 // Maps the asset ID to the assembly
116 119
117 private Dictionary<UUID, string> m_Assemblies = 120 private Dictionary<UUID, string> m_Assemblies =
@@ -134,6 +137,71 @@ namespace OpenSim.Region.ScriptEngine.XEngine
134 IWorkItemResult m_CurrentCompile = null; 137 IWorkItemResult m_CurrentCompile = null;
135 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>(); 138 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>();
136 139
140 private void lockScriptsForRead(bool locked)
141 {
142 if (locked)
143 {
144 if (m_scriptsLock.RecursiveReadCount > 0)
145 {
146 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.");
147 m_scriptsLock.ExitReadLock();
148 }
149 if (m_scriptsLock.RecursiveWriteCount > 0)
150 {
151 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
152 m_scriptsLock.ExitWriteLock();
153 }
154
155 while (!m_scriptsLock.TryEnterReadLock(60000))
156 {
157 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.");
158 if (m_scriptsLock.IsWriteLockHeld)
159 {
160 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
161 }
162 }
163 }
164 else
165 {
166 if (m_scriptsLock.RecursiveReadCount > 0)
167 {
168 m_scriptsLock.ExitReadLock();
169 }
170 }
171 }
172 private void lockScriptsForWrite(bool locked)
173 {
174 if (locked)
175 {
176 if (m_scriptsLock.RecursiveReadCount > 0)
177 {
178 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.");
179 m_scriptsLock.ExitReadLock();
180 }
181 if (m_scriptsLock.RecursiveWriteCount > 0)
182 {
183 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
184 m_scriptsLock.ExitWriteLock();
185 }
186
187 while (!m_scriptsLock.TryEnterWriteLock(60000))
188 {
189 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.");
190 if (m_scriptsLock.IsWriteLockHeld)
191 {
192 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
193 }
194 }
195 }
196 else
197 {
198 if (m_scriptsLock.RecursiveWriteCount > 0)
199 {
200 m_scriptsLock.ExitWriteLock();
201 }
202 }
203 }
204
137 public string ScriptEngineName 205 public string ScriptEngineName
138 { 206 {
139 get { return "XEngine"; } 207 get { return "XEngine"; }
@@ -527,44 +595,37 @@ namespace OpenSim.Region.ScriptEngine.XEngine
527 { 595 {
528 if (!m_Enabled) 596 if (!m_Enabled)
529 return; 597 return;
530 598 lockScriptsForRead(true);
531 lock (m_Scripts) 599 foreach (IScriptInstance instance in m_Scripts.Values)
532 { 600 {
533 m_log.InfoFormat( 601 // Force a final state save
534 "[XEngine]: Shutting down {0} scripts in {1}", m_Scripts.Count, m_Scene.RegionInfo.RegionName); 602 //
535 603 if (m_Assemblies.ContainsKey(instance.AssetID))
536 foreach (IScriptInstance instance in m_Scripts.Values)
537 { 604 {
538 // Force a final state save 605 string assembly = m_Assemblies[instance.AssetID];
539 // 606 instance.SaveState(assembly);
540 if (m_Assemblies.ContainsKey(instance.AssetID)) 607 }
541 {
542 string assembly = m_Assemblies[instance.AssetID];
543 instance.SaveState(assembly);
544 }
545 608
546 // Clear the event queue and abort the instance thread 609 // Clear the event queue and abort the instance thread
547 // 610 //
548 instance.ClearQueue(); 611 instance.ClearQueue();
549 instance.Stop(0); 612 instance.Stop(0);
550 613
551 // Release events, timer, etc 614 // Release events, timer, etc
552 // 615 //
553 instance.DestroyScriptInstance(); 616 instance.DestroyScriptInstance();
554 617
555 // Unload scripts and app domains. 618 // Unload scripts and app domains
556 // Must be done explicitly because they have infinite 619 // Must be done explicitly because they have infinite
557 // lifetime. 620 // lifetime
558 // However, don't bother to do this if the simulator is shutting 621 //
559 // down since it takes a long time with many scripts. 622 if (!m_SimulatorShuttingDown)
560 if (!m_SimulatorShuttingDown) 623 {
624 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
625 if (m_DomainScripts[instance.AppDomain].Count == 0)
561 { 626 {
562 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 627 m_DomainScripts.Remove(instance.AppDomain);
563 if (m_DomainScripts[instance.AppDomain].Count == 0) 628 UnloadAppDomain(instance.AppDomain);
564 {
565 m_DomainScripts.Remove(instance.AppDomain);
566 UnloadAppDomain(instance.AppDomain);
567 }
568 } 629 }
569 } 630 }
570 631
@@ -573,6 +634,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
573 m_Assemblies.Clear(); 634 m_Assemblies.Clear();
574 m_DomainScripts.Clear(); 635 m_DomainScripts.Clear();
575 } 636 }
637 lockScriptsForRead(false);
638 lockScriptsForWrite(true);
639 m_Scripts.Clear();
640 lockScriptsForWrite(false);
641 m_PrimObjects.Clear();
642 m_Assemblies.Clear();
643 m_DomainScripts.Clear();
644
576 lock (m_ScriptEngines) 645 lock (m_ScriptEngines)
577 { 646 {
578 m_ScriptEngines.Remove(this); 647 m_ScriptEngines.Remove(this);
@@ -637,22 +706,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
637 706
638 List<IScriptInstance> instances = new List<IScriptInstance>(); 707 List<IScriptInstance> instances = new List<IScriptInstance>();
639 708
640 lock (m_Scripts) 709 lockScriptsForRead(true);
641 { 710 foreach (IScriptInstance instance in m_Scripts.Values)
642 foreach (IScriptInstance instance in m_Scripts.Values)
643 instances.Add(instance); 711 instances.Add(instance);
644 } 712 lockScriptsForRead(false);
645 713
646 foreach (IScriptInstance i in instances) 714 foreach (IScriptInstance i in instances)
647 { 715 {
648 string assembly = String.Empty; 716 string assembly = String.Empty;
649 717
650 lock (m_Scripts) 718
651 {
652 if (!m_Assemblies.ContainsKey(i.AssetID)) 719 if (!m_Assemblies.ContainsKey(i.AssetID))
653 continue; 720 continue;
654 assembly = m_Assemblies[i.AssetID]; 721 assembly = m_Assemblies[i.AssetID];
655 } 722
656 723
657 i.SaveState(assembly); 724 i.SaveState(assembly);
658 } 725 }
@@ -996,91 +1063,95 @@ namespace OpenSim.Region.ScriptEngine.XEngine
996 } 1063 }
997 1064
998 ScriptInstance instance = null; 1065 ScriptInstance instance = null;
999 lock (m_Scripts) 1066 // Create the object record
1067 lockScriptsForRead(true);
1068 if ((!m_Scripts.ContainsKey(itemID)) ||
1069 (m_Scripts[itemID].AssetID != assetID))
1000 { 1070 {
1001 // Create the object record 1071 lockScriptsForRead(false);
1002 if ((!m_Scripts.ContainsKey(itemID)) ||
1003 (m_Scripts[itemID].AssetID != assetID))
1004 {
1005 UUID appDomain = assetID;
1006 1072
1007 if (part.ParentGroup.IsAttachment) 1073 UUID appDomain = assetID;
1008 appDomain = part.ParentGroup.RootPart.UUID;
1009 1074
1010 if (!m_AppDomains.ContainsKey(appDomain)) 1075 if (part.ParentGroup.IsAttachment)
1011 { 1076 appDomain = part.ParentGroup.RootPart.UUID;
1012 try
1013 {
1014 AppDomainSetup appSetup = new AppDomainSetup();
1015 appSetup.PrivateBinPath = Path.Combine(
1016 m_ScriptEnginesPath,
1017 m_Scene.RegionInfo.RegionID.ToString());
1018
1019 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
1020 Evidence evidence = new Evidence(baseEvidence);
1021
1022 AppDomain sandbox;
1023 if (m_AppDomainLoading)
1024 sandbox = AppDomain.CreateDomain(
1025 m_Scene.RegionInfo.RegionID.ToString(),
1026 evidence, appSetup);
1027 else
1028 sandbox = AppDomain.CurrentDomain;
1029
1030 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1031 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1032 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1033 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1034 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1035 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1036 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1037
1038 m_AppDomains[appDomain] = sandbox;
1039 1077
1040 m_AppDomains[appDomain].AssemblyResolve += 1078 if (!m_AppDomains.ContainsKey(appDomain))
1041 new ResolveEventHandler( 1079 {
1042 AssemblyResolver.OnAssemblyResolve); 1080 try
1043 m_DomainScripts[appDomain] = new List<UUID>(); 1081 {
1044 } 1082 AppDomainSetup appSetup = new AppDomainSetup();
1045 catch (Exception e) 1083 appSetup.PrivateBinPath = Path.Combine(
1084 m_ScriptEnginesPath,
1085 m_Scene.RegionInfo.RegionID.ToString());
1086
1087 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
1088 Evidence evidence = new Evidence(baseEvidence);
1089
1090 AppDomain sandbox;
1091 if (m_AppDomainLoading)
1092 sandbox = AppDomain.CreateDomain(
1093 m_Scene.RegionInfo.RegionID.ToString(),
1094 evidence, appSetup);
1095 else
1096 sandbox = AppDomain.CurrentDomain;
1097
1098 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1099 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1100 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1101 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1102 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1103 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1104 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1105
1106 m_AppDomains[appDomain] = sandbox;
1107
1108 m_AppDomains[appDomain].AssemblyResolve +=
1109 new ResolveEventHandler(
1110 AssemblyResolver.OnAssemblyResolve);
1111 m_DomainScripts[appDomain] = new List<UUID>();
1112 }
1113 catch (Exception e)
1114 {
1115 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
1116 m_ScriptErrorMessage += "Exception creating app domain:\n";
1117 m_ScriptFailCount++;
1118 lock (m_AddingAssemblies)
1046 { 1119 {
1047 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); 1120 m_AddingAssemblies[assembly]--;
1048 m_ScriptErrorMessage += "Exception creating app domain:\n";
1049 m_ScriptFailCount++;
1050 lock (m_AddingAssemblies)
1051 {
1052 m_AddingAssemblies[assembly]--;
1053 }
1054 return false;
1055 } 1121 }
1122 return false;
1056 } 1123 }
1057 m_DomainScripts[appDomain].Add(itemID); 1124 }
1058 1125 m_DomainScripts[appDomain].Add(itemID);
1059 instance = new ScriptInstance(this, part, 1126
1060 itemID, assetID, assembly, 1127 instance = new ScriptInstance(this, part,
1061 m_AppDomains[appDomain], 1128 itemID, assetID, assembly,
1062 part.ParentGroup.RootPart.Name, 1129 m_AppDomains[appDomain],
1063 item.Name, startParam, postOnRez, 1130 part.ParentGroup.RootPart.Name,
1064 stateSource, m_MaxScriptQueue); 1131 item.Name, startParam, postOnRez,
1065 1132 stateSource, m_MaxScriptQueue);
1066 m_log.DebugFormat( 1133
1067 "[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", 1134 m_log.DebugFormat(
1068 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, 1135 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1136 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
1069 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); 1137 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1070 1138
1071 if (presence != null) 1139 if (presence != null)
1072 { 1140 {
1073 ShowScriptSaveResponse(item.OwnerID, 1141 ShowScriptSaveResponse(item.OwnerID,
1074 assetID, "Compile successful", true); 1142 assetID, "Compile successful", true);
1075 }
1076
1077 instance.AppDomain = appDomain;
1078 instance.LineMap = linemap;
1079
1080 m_Scripts[itemID] = instance;
1081 } 1143 }
1082 }
1083 1144
1145 instance.AppDomain = appDomain;
1146 instance.LineMap = linemap;
1147 lockScriptsForWrite(true);
1148 m_Scripts[itemID] = instance;
1149 lockScriptsForWrite(false);
1150 }
1151 else
1152 {
1153 lockScriptsForRead(false);
1154 }
1084 lock (m_PrimObjects) 1155 lock (m_PrimObjects)
1085 { 1156 {
1086 if (!m_PrimObjects.ContainsKey(localID)) 1157 if (!m_PrimObjects.ContainsKey(localID))
@@ -1098,9 +1169,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1098 m_AddingAssemblies[assembly]--; 1169 m_AddingAssemblies[assembly]--;
1099 } 1170 }
1100 1171
1101 if (instance != null) 1172 if (instance!=null)
1102 instance.Init(); 1173 instance.Init();
1103 1174
1104 return true; 1175 return true;
1105 } 1176 }
1106 1177
@@ -1113,18 +1184,28 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1113 m_CompileDict.Remove(itemID); 1184 m_CompileDict.Remove(itemID);
1114 } 1185 }
1115 1186
1116 IScriptInstance instance = null; 1187 lockScriptsForRead(true);
1117 1188 // Do we even have it?
1118 lock (m_Scripts) 1189 if (!m_Scripts.ContainsKey(itemID))
1119 { 1190 {
1120 // Do we even have it? 1191 // Do we even have it?
1121 if (!m_Scripts.ContainsKey(itemID)) 1192 if (!m_Scripts.ContainsKey(itemID))
1122 return; 1193 return;
1123 1194
1124 instance = m_Scripts[itemID]; 1195 lockScriptsForRead(false);
1196 lockScriptsForWrite(true);
1125 m_Scripts.Remove(itemID); 1197 m_Scripts.Remove(itemID);
1198 lockScriptsForWrite(false);
1199
1200 return;
1126 } 1201 }
1202
1127 1203
1204 IScriptInstance instance=m_Scripts[itemID];
1205 lockScriptsForRead(false);
1206 lockScriptsForWrite(true);
1207 m_Scripts.Remove(itemID);
1208 lockScriptsForWrite(false);
1128 instance.ClearQueue(); 1209 instance.ClearQueue();
1129 1210
1130 // Give the script some time to finish processing its last event. Simply aborting the script thread can 1211 // Give the script some time to finish processing its last event. Simply aborting the script thread can
@@ -1163,8 +1244,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1163 1244
1164 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 1245 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
1165 if (handlerObjectRemoved != null) 1246 if (handlerObjectRemoved != null)
1166 handlerObjectRemoved(instance.ObjectID); 1247 {
1248 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
1249 handlerObjectRemoved(part.UUID);
1250 }
1167 1251
1252 CleanAssemblies();
1253
1168 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 1254 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
1169 if (handlerScriptRemoved != null) 1255 if (handlerScriptRemoved != null)
1170 handlerScriptRemoved(itemID); 1256 handlerScriptRemoved(itemID);
@@ -1306,7 +1392,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1306 return false; 1392 return false;
1307 1393
1308 uuids = m_PrimObjects[localID]; 1394 uuids = m_PrimObjects[localID];
1309 } 1395
1310 1396
1311 foreach (UUID itemID in uuids) 1397 foreach (UUID itemID in uuids)
1312 { 1398 {
@@ -1324,6 +1410,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1324 result = true; 1410 result = true;
1325 } 1411 }
1326 } 1412 }
1413 }
1327 1414
1328 return result; 1415 return result;
1329 } 1416 }
@@ -1425,12 +1512,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1425 private IScriptInstance GetInstance(UUID itemID) 1512 private IScriptInstance GetInstance(UUID itemID)
1426 { 1513 {
1427 IScriptInstance instance; 1514 IScriptInstance instance;
1428 lock (m_Scripts) 1515 lockScriptsForRead(true);
1516 if (!m_Scripts.ContainsKey(itemID))
1429 { 1517 {
1430 if (!m_Scripts.ContainsKey(itemID)) 1518 lockScriptsForRead(false);
1431 return null; 1519 return null;
1432 instance = m_Scripts[itemID];
1433 } 1520 }
1521 instance = m_Scripts[itemID];
1522 lockScriptsForRead(false);
1434 return instance; 1523 return instance;
1435 } 1524 }
1436 1525
@@ -1454,6 +1543,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1454 return false; 1543 return false;
1455 } 1544 }
1456 1545
1546 [DebuggerNonUserCode]
1457 public void ApiResetScript(UUID itemID) 1547 public void ApiResetScript(UUID itemID)
1458 { 1548 {
1459 IScriptInstance instance = GetInstance(itemID); 1549 IScriptInstance instance = GetInstance(itemID);
@@ -1505,6 +1595,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1505 return UUID.Zero; 1595 return UUID.Zero;
1506 } 1596 }
1507 1597
1598 [DebuggerNonUserCode]
1508 public void SetState(UUID itemID, string newState) 1599 public void SetState(UUID itemID, string newState)
1509 { 1600 {
1510 IScriptInstance instance = GetInstance(itemID); 1601 IScriptInstance instance = GetInstance(itemID);
@@ -1527,11 +1618,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1527 1618
1528 List<IScriptInstance> instances = new List<IScriptInstance>(); 1619 List<IScriptInstance> instances = new List<IScriptInstance>();
1529 1620
1530 lock (m_Scripts) 1621 lockScriptsForRead(true);
1531 { 1622 foreach (IScriptInstance instance in m_Scripts.Values)
1532 foreach (IScriptInstance instance in m_Scripts.Values)
1533 instances.Add(instance); 1623 instances.Add(instance);
1534 } 1624 lockScriptsForRead(false);
1535 1625
1536 foreach (IScriptInstance i in instances) 1626 foreach (IScriptInstance i in instances)
1537 { 1627 {
@@ -1969,5 +2059,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1969// else 2059// else
1970// m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID); 2060// m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID);
1971 } 2061 }
2062
2063 public bool HasScript(UUID itemID, out bool running)
2064 {
2065 running = true;
2066
2067 IScriptInstance instance = GetInstance(itemID);
2068 if (instance == null)
2069 return false;
2070
2071 running = instance.Running;
2072 return true;
2073 }
1972 } 2074 }
1973} \ No newline at end of file 2075}