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.cs361
1 files changed, 230 insertions, 131 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index c68f03f..02d47bd 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;
@@ -109,6 +110,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
109 private Dictionary<UUID, IScriptInstance> m_Scripts = 110 private Dictionary<UUID, IScriptInstance> m_Scripts =
110 new Dictionary<UUID, IScriptInstance>(); 111 new Dictionary<UUID, IScriptInstance>();
111 112
113 private OpenMetaverse.ReaderWriterLockSlim m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
114
112 // Maps the asset ID to the assembly 115 // Maps the asset ID to the assembly
113 116
114 private Dictionary<UUID, string> m_Assemblies = 117 private Dictionary<UUID, string> m_Assemblies =
@@ -131,6 +134,71 @@ namespace OpenSim.Region.ScriptEngine.XEngine
131 IWorkItemResult m_CurrentCompile = null; 134 IWorkItemResult m_CurrentCompile = null;
132 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>(); 135 private Dictionary<UUID, int> m_CompileDict = new Dictionary<UUID, int>();
133 136
137 private void lockScriptsForRead(bool locked)
138 {
139 if (locked)
140 {
141 if (m_scriptsLock.RecursiveReadCount > 0)
142 {
143 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.");
144 m_scriptsLock.ExitReadLock();
145 }
146 if (m_scriptsLock.RecursiveWriteCount > 0)
147 {
148 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
149 m_scriptsLock.ExitWriteLock();
150 }
151
152 while (!m_scriptsLock.TryEnterReadLock(60000))
153 {
154 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.");
155 if (m_scriptsLock.IsWriteLockHeld)
156 {
157 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
158 }
159 }
160 }
161 else
162 {
163 if (m_scriptsLock.RecursiveReadCount > 0)
164 {
165 m_scriptsLock.ExitReadLock();
166 }
167 }
168 }
169 private void lockScriptsForWrite(bool locked)
170 {
171 if (locked)
172 {
173 if (m_scriptsLock.RecursiveReadCount > 0)
174 {
175 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.");
176 m_scriptsLock.ExitReadLock();
177 }
178 if (m_scriptsLock.RecursiveWriteCount > 0)
179 {
180 m_log.Error("[XEngine.m_Scripts] Recursive write lock requested. This should not happen and means something needs to be fixed.");
181 m_scriptsLock.ExitWriteLock();
182 }
183
184 while (!m_scriptsLock.TryEnterWriteLock(60000))
185 {
186 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.");
187 if (m_scriptsLock.IsWriteLockHeld)
188 {
189 m_scriptsLock = new OpenMetaverse.ReaderWriterLockSlim();
190 }
191 }
192 }
193 else
194 {
195 if (m_scriptsLock.RecursiveWriteCount > 0)
196 {
197 m_scriptsLock.ExitWriteLock();
198 }
199 }
200 }
201
134 public string ScriptEngineName 202 public string ScriptEngineName
135 { 203 {
136 get { return "XEngine"; } 204 get { return "XEngine"; }
@@ -501,44 +569,37 @@ namespace OpenSim.Region.ScriptEngine.XEngine
501 { 569 {
502 if (!m_Enabled) 570 if (!m_Enabled)
503 return; 571 return;
504 572 lockScriptsForRead(true);
505 lock (m_Scripts) 573 foreach (IScriptInstance instance in m_Scripts.Values)
506 { 574 {
507 m_log.InfoFormat( 575 // Force a final state save
508 "[XEngine]: Shutting down {0} scripts in {1}", m_Scripts.Count, m_Scene.RegionInfo.RegionName); 576 //
509 577 if (m_Assemblies.ContainsKey(instance.AssetID))
510 foreach (IScriptInstance instance in m_Scripts.Values)
511 { 578 {
512 // Force a final state save 579 string assembly = m_Assemblies[instance.AssetID];
513 // 580 instance.SaveState(assembly);
514 if (m_Assemblies.ContainsKey(instance.AssetID)) 581 }
515 {
516 string assembly = m_Assemblies[instance.AssetID];
517 instance.SaveState(assembly);
518 }
519 582
520 // Clear the event queue and abort the instance thread 583 // Clear the event queue and abort the instance thread
521 // 584 //
522 instance.ClearQueue(); 585 instance.ClearQueue();
523 instance.Stop(0); 586 instance.Stop(0);
524 587
525 // Release events, timer, etc 588 // Release events, timer, etc
526 // 589 //
527 instance.DestroyScriptInstance(); 590 instance.DestroyScriptInstance();
528 591
529 // Unload scripts and app domains. 592 // Unload scripts and app domains
530 // Must be done explicitly because they have infinite 593 // Must be done explicitly because they have infinite
531 // lifetime. 594 // lifetime
532 // However, don't bother to do this if the simulator is shutting 595 //
533 // down since it takes a long time with many scripts. 596 if (!m_SimulatorShuttingDown)
534 if (!m_SimulatorShuttingDown) 597 {
598 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
599 if (m_DomainScripts[instance.AppDomain].Count == 0)
535 { 600 {
536 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 601 m_DomainScripts.Remove(instance.AppDomain);
537 if (m_DomainScripts[instance.AppDomain].Count == 0) 602 UnloadAppDomain(instance.AppDomain);
538 {
539 m_DomainScripts.Remove(instance.AppDomain);
540 UnloadAppDomain(instance.AppDomain);
541 }
542 } 603 }
543 } 604 }
544 605
@@ -547,6 +608,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
547 m_Assemblies.Clear(); 608 m_Assemblies.Clear();
548 m_DomainScripts.Clear(); 609 m_DomainScripts.Clear();
549 } 610 }
611 lockScriptsForRead(false);
612 lockScriptsForWrite(true);
613 m_Scripts.Clear();
614 lockScriptsForWrite(false);
615 m_PrimObjects.Clear();
616 m_Assemblies.Clear();
617 m_DomainScripts.Clear();
618
550 lock (m_ScriptEngines) 619 lock (m_ScriptEngines)
551 { 620 {
552 m_ScriptEngines.Remove(this); 621 m_ScriptEngines.Remove(this);
@@ -611,22 +680,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
611 680
612 List<IScriptInstance> instances = new List<IScriptInstance>(); 681 List<IScriptInstance> instances = new List<IScriptInstance>();
613 682
614 lock (m_Scripts) 683 lockScriptsForRead(true);
615 { 684 foreach (IScriptInstance instance in m_Scripts.Values)
616 foreach (IScriptInstance instance in m_Scripts.Values)
617 instances.Add(instance); 685 instances.Add(instance);
618 } 686 lockScriptsForRead(false);
619 687
620 foreach (IScriptInstance i in instances) 688 foreach (IScriptInstance i in instances)
621 { 689 {
622 string assembly = String.Empty; 690 string assembly = String.Empty;
623 691
624 lock (m_Scripts) 692
625 {
626 if (!m_Assemblies.ContainsKey(i.AssetID)) 693 if (!m_Assemblies.ContainsKey(i.AssetID))
627 continue; 694 continue;
628 assembly = m_Assemblies[i.AssetID]; 695 assembly = m_Assemblies[i.AssetID];
629 } 696
630 697
631 i.SaveState(assembly); 698 i.SaveState(assembly);
632 } 699 }
@@ -970,92 +1037,95 @@ namespace OpenSim.Region.ScriptEngine.XEngine
970 } 1037 }
971 1038
972 ScriptInstance instance = null; 1039 ScriptInstance instance = null;
973 lock (m_Scripts) 1040 // Create the object record
1041 lockScriptsForRead(true);
1042 if ((!m_Scripts.ContainsKey(itemID)) ||
1043 (m_Scripts[itemID].AssetID != assetID))
974 { 1044 {
975 // Create the object record 1045 lockScriptsForRead(false);
976 1046
977 if ((!m_Scripts.ContainsKey(itemID)) || 1047 UUID appDomain = assetID;
978 (m_Scripts[itemID].AssetID != assetID))
979 {
980 UUID appDomain = assetID;
981 1048
982 if (part.ParentGroup.IsAttachment) 1049 if (part.ParentGroup.IsAttachment)
983 appDomain = part.ParentGroup.RootPart.UUID; 1050 appDomain = part.ParentGroup.RootPart.UUID;
984 1051
985 if (!m_AppDomains.ContainsKey(appDomain)) 1052 if (!m_AppDomains.ContainsKey(appDomain))
1053 {
1054 try
986 { 1055 {
987 try 1056 AppDomainSetup appSetup = new AppDomainSetup();
988 { 1057 appSetup.PrivateBinPath = Path.Combine(
989 AppDomainSetup appSetup = new AppDomainSetup(); 1058 m_ScriptEnginesPath,
990 appSetup.PrivateBinPath = Path.Combine( 1059 m_Scene.RegionInfo.RegionID.ToString());
991 m_ScriptEnginesPath, 1060
992 m_Scene.RegionInfo.RegionID.ToString()); 1061 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
993 1062 Evidence evidence = new Evidence(baseEvidence);
994 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence; 1063
995 Evidence evidence = new Evidence(baseEvidence); 1064 AppDomain sandbox;
996 1065 if (m_AppDomainLoading)
997 AppDomain sandbox; 1066 sandbox = AppDomain.CreateDomain(
998 if (m_AppDomainLoading) 1067 m_Scene.RegionInfo.RegionID.ToString(),
999 sandbox = AppDomain.CreateDomain( 1068 evidence, appSetup);
1000 m_Scene.RegionInfo.RegionID.ToString(), 1069 else
1001 evidence, appSetup); 1070 sandbox = AppDomain.CurrentDomain;
1002 else 1071
1003 sandbox = AppDomain.CurrentDomain; 1072 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1004 1073 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1005 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel(); 1074 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1006 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition(); 1075 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1007 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet"); 1076 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1008 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet); 1077 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1009 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement); 1078 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1010 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup; 1079
1011 //sandbox.SetAppDomainPolicy(sandboxPolicy); 1080 m_AppDomains[appDomain] = sandbox;
1012 1081
1013 m_AppDomains[appDomain] = sandbox; 1082 m_AppDomains[appDomain].AssemblyResolve +=
1014 1083 new ResolveEventHandler(
1015 m_AppDomains[appDomain].AssemblyResolve += 1084 AssemblyResolver.OnAssemblyResolve);
1016 new ResolveEventHandler( 1085 m_DomainScripts[appDomain] = new List<UUID>();
1017 AssemblyResolver.OnAssemblyResolve); 1086 }
1018 m_DomainScripts[appDomain] = new List<UUID>(); 1087 catch (Exception e)
1019 } 1088 {
1020 catch (Exception e) 1089 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
1090 m_ScriptErrorMessage += "Exception creating app domain:\n";
1091 m_ScriptFailCount++;
1092 lock (m_AddingAssemblies)
1021 { 1093 {
1022 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); 1094 m_AddingAssemblies[assembly]--;
1023 m_ScriptErrorMessage += "Exception creating app domain:\n";
1024 m_ScriptFailCount++;
1025 lock (m_AddingAssemblies)
1026 {
1027 m_AddingAssemblies[assembly]--;
1028 }
1029 return false;
1030 } 1095 }
1096 return false;
1031 } 1097 }
1032 m_DomainScripts[appDomain].Add(itemID); 1098 }
1033 1099 m_DomainScripts[appDomain].Add(itemID);
1034 instance = new ScriptInstance(this, part, 1100
1035 itemID, assetID, assembly, 1101 instance = new ScriptInstance(this, part,
1036 m_AppDomains[appDomain], 1102 itemID, assetID, assembly,
1037 part.ParentGroup.RootPart.Name, 1103 m_AppDomains[appDomain],
1038 item.Name, startParam, postOnRez, 1104 part.ParentGroup.RootPart.Name,
1039 stateSource, m_MaxScriptQueue); 1105 item.Name, startParam, postOnRez,
1040 1106 stateSource, m_MaxScriptQueue);
1041 m_log.DebugFormat( 1107
1042 "[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", 1108 m_log.DebugFormat(
1043 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, 1109 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1110 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
1044 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); 1111 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1045 1112
1046 if (presence != null) 1113 if (presence != null)
1047 { 1114 {
1048 ShowScriptSaveResponse(item.OwnerID, 1115 ShowScriptSaveResponse(item.OwnerID,
1049 assetID, "Compile successful", true); 1116 assetID, "Compile successful", true);
1050 }
1051
1052 instance.AppDomain = appDomain;
1053 instance.LineMap = linemap;
1054
1055 m_Scripts[itemID] = instance;
1056 } 1117 }
1057 }
1058 1118
1119 instance.AppDomain = appDomain;
1120 instance.LineMap = linemap;
1121 lockScriptsForWrite(true);
1122 m_Scripts[itemID] = instance;
1123 lockScriptsForWrite(false);
1124 }
1125 else
1126 {
1127 lockScriptsForRead(false);
1128 }
1059 lock (m_PrimObjects) 1129 lock (m_PrimObjects)
1060 { 1130 {
1061 if (!m_PrimObjects.ContainsKey(localID)) 1131 if (!m_PrimObjects.ContainsKey(localID))
@@ -1074,9 +1144,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1074 m_AddingAssemblies[assembly]--; 1144 m_AddingAssemblies[assembly]--;
1075 } 1145 }
1076 1146
1077 if (instance != null) 1147 if (instance!=null)
1078 instance.Init(); 1148 instance.Init();
1079 1149
1080 return true; 1150 return true;
1081 } 1151 }
1082 1152
@@ -1089,20 +1159,31 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1089 m_CompileDict.Remove(itemID); 1159 m_CompileDict.Remove(itemID);
1090 } 1160 }
1091 1161
1092 IScriptInstance instance = null; 1162 lockScriptsForRead(true);
1093 1163 // Do we even have it?
1094 lock (m_Scripts) 1164 if (!m_Scripts.ContainsKey(itemID))
1095 { 1165 {
1096 // Do we even have it? 1166 // Do we even have it?
1097 if (!m_Scripts.ContainsKey(itemID)) 1167 if (!m_Scripts.ContainsKey(itemID))
1098 return; 1168 return;
1099 1169
1100 instance = m_Scripts[itemID]; 1170 lockScriptsForRead(false);
1171 lockScriptsForWrite(true);
1101 m_Scripts.Remove(itemID); 1172 m_Scripts.Remove(itemID);
1173 lockScriptsForWrite(false);
1174
1175 return;
1102 } 1176 }
1177
1103 1178
1179 IScriptInstance instance=m_Scripts[itemID];
1180 lockScriptsForRead(false);
1181 lockScriptsForWrite(true);
1182 m_Scripts.Remove(itemID);
1183 lockScriptsForWrite(false);
1104 instance.ClearQueue(); 1184 instance.ClearQueue();
1105 instance.Stop(0); 1185 instance.Stop(0);
1186
1106// bool objectRemoved = false; 1187// bool objectRemoved = false;
1107 1188
1108 lock (m_PrimObjects) 1189 lock (m_PrimObjects)
@@ -1138,10 +1219,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1138 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 1219 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
1139 if (handlerObjectRemoved != null) 1220 if (handlerObjectRemoved != null)
1140 { 1221 {
1141 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID); 1222 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
1142 handlerObjectRemoved(part.UUID); 1223 handlerObjectRemoved(part.UUID);
1143 } 1224 }
1144 1225
1226 CleanAssemblies();
1227
1145 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 1228 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
1146 if (handlerScriptRemoved != null) 1229 if (handlerScriptRemoved != null)
1147 handlerScriptRemoved(itemID); 1230 handlerScriptRemoved(itemID);
@@ -1283,7 +1366,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1283 return false; 1366 return false;
1284 1367
1285 uuids = m_PrimObjects[localID]; 1368 uuids = m_PrimObjects[localID];
1286 } 1369
1287 1370
1288 foreach (UUID itemID in uuids) 1371 foreach (UUID itemID in uuids)
1289 { 1372 {
@@ -1301,6 +1384,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1301 result = true; 1384 result = true;
1302 } 1385 }
1303 } 1386 }
1387 }
1304 1388
1305 return result; 1389 return result;
1306 } 1390 }
@@ -1402,12 +1486,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1402 private IScriptInstance GetInstance(UUID itemID) 1486 private IScriptInstance GetInstance(UUID itemID)
1403 { 1487 {
1404 IScriptInstance instance; 1488 IScriptInstance instance;
1405 lock (m_Scripts) 1489 lockScriptsForRead(true);
1490 if (!m_Scripts.ContainsKey(itemID))
1406 { 1491 {
1407 if (!m_Scripts.ContainsKey(itemID)) 1492 lockScriptsForRead(false);
1408 return null; 1493 return null;
1409 instance = m_Scripts[itemID];
1410 } 1494 }
1495 instance = m_Scripts[itemID];
1496 lockScriptsForRead(false);
1411 return instance; 1497 return instance;
1412 } 1498 }
1413 1499
@@ -1431,6 +1517,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1431 return false; 1517 return false;
1432 } 1518 }
1433 1519
1520 [DebuggerNonUserCode]
1434 public void ApiResetScript(UUID itemID) 1521 public void ApiResetScript(UUID itemID)
1435 { 1522 {
1436 IScriptInstance instance = GetInstance(itemID); 1523 IScriptInstance instance = GetInstance(itemID);
@@ -1482,6 +1569,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1482 return UUID.Zero; 1569 return UUID.Zero;
1483 } 1570 }
1484 1571
1572 [DebuggerNonUserCode]
1485 public void SetState(UUID itemID, string newState) 1573 public void SetState(UUID itemID, string newState)
1486 { 1574 {
1487 IScriptInstance instance = GetInstance(itemID); 1575 IScriptInstance instance = GetInstance(itemID);
@@ -1504,11 +1592,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1504 1592
1505 List<IScriptInstance> instances = new List<IScriptInstance>(); 1593 List<IScriptInstance> instances = new List<IScriptInstance>();
1506 1594
1507 lock (m_Scripts) 1595 lockScriptsForRead(true);
1508 { 1596 foreach (IScriptInstance instance in m_Scripts.Values)
1509 foreach (IScriptInstance instance in m_Scripts.Values)
1510 instances.Add(instance); 1597 instances.Add(instance);
1511 } 1598 lockScriptsForRead(false);
1512 1599
1513 foreach (IScriptInstance i in instances) 1600 foreach (IScriptInstance i in instances)
1514 { 1601 {
@@ -1893,5 +1980,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1893// else 1980// else
1894// m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID); 1981// m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID);
1895 } 1982 }
1983
1984 public bool HasScript(UUID itemID, out bool running)
1985 {
1986 running = true;
1987
1988 IScriptInstance instance = GetInstance(itemID);
1989 if (instance == null)
1990 return false;
1991
1992 running = instance.Running;
1993 return true;
1994 }
1896 } 1995 }
1897} \ No newline at end of file 1996}