aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/XEngine
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine/XEngine')
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs362
1 files changed, 231 insertions, 131 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index ab41873..1d3ba6c 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"; }
@@ -518,44 +586,37 @@ namespace OpenSim.Region.ScriptEngine.XEngine
518 { 586 {
519 if (!m_Enabled) 587 if (!m_Enabled)
520 return; 588 return;
521 589 lockScriptsForRead(true);
522 lock (m_Scripts) 590 foreach (IScriptInstance instance in m_Scripts.Values)
523 { 591 {
524 m_log.InfoFormat( 592 // Force a final state save
525 "[XEngine]: Shutting down {0} scripts in {1}", m_Scripts.Count, m_Scene.RegionInfo.RegionName); 593 //
526 594 if (m_Assemblies.ContainsKey(instance.AssetID))
527 foreach (IScriptInstance instance in m_Scripts.Values)
528 { 595 {
529 // Force a final state save 596 string assembly = m_Assemblies[instance.AssetID];
530 // 597 instance.SaveState(assembly);
531 if (m_Assemblies.ContainsKey(instance.AssetID)) 598 }
532 {
533 string assembly = m_Assemblies[instance.AssetID];
534 instance.SaveState(assembly);
535 }
536 599
537 // Clear the event queue and abort the instance thread 600 // Clear the event queue and abort the instance thread
538 // 601 //
539 instance.ClearQueue(); 602 instance.ClearQueue();
540 instance.Stop(0); 603 instance.Stop(0);
541 604
542 // Release events, timer, etc 605 // Release events, timer, etc
543 // 606 //
544 instance.DestroyScriptInstance(); 607 instance.DestroyScriptInstance();
545 608
546 // Unload scripts and app domains. 609 // Unload scripts and app domains
547 // Must be done explicitly because they have infinite 610 // Must be done explicitly because they have infinite
548 // lifetime. 611 // lifetime
549 // However, don't bother to do this if the simulator is shutting 612 //
550 // down since it takes a long time with many scripts. 613 if (!m_SimulatorShuttingDown)
551 if (!m_SimulatorShuttingDown) 614 {
615 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID);
616 if (m_DomainScripts[instance.AppDomain].Count == 0)
552 { 617 {
553 m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); 618 m_DomainScripts.Remove(instance.AppDomain);
554 if (m_DomainScripts[instance.AppDomain].Count == 0) 619 UnloadAppDomain(instance.AppDomain);
555 {
556 m_DomainScripts.Remove(instance.AppDomain);
557 UnloadAppDomain(instance.AppDomain);
558 }
559 } 620 }
560 } 621 }
561 622
@@ -564,6 +625,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
564 m_Assemblies.Clear(); 625 m_Assemblies.Clear();
565 m_DomainScripts.Clear(); 626 m_DomainScripts.Clear();
566 } 627 }
628 lockScriptsForRead(false);
629 lockScriptsForWrite(true);
630 m_Scripts.Clear();
631 lockScriptsForWrite(false);
632 m_PrimObjects.Clear();
633 m_Assemblies.Clear();
634 m_DomainScripts.Clear();
635
567 lock (m_ScriptEngines) 636 lock (m_ScriptEngines)
568 { 637 {
569 m_ScriptEngines.Remove(this); 638 m_ScriptEngines.Remove(this);
@@ -628,22 +697,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
628 697
629 List<IScriptInstance> instances = new List<IScriptInstance>(); 698 List<IScriptInstance> instances = new List<IScriptInstance>();
630 699
631 lock (m_Scripts) 700 lockScriptsForRead(true);
632 { 701 foreach (IScriptInstance instance in m_Scripts.Values)
633 foreach (IScriptInstance instance in m_Scripts.Values)
634 instances.Add(instance); 702 instances.Add(instance);
635 } 703 lockScriptsForRead(false);
636 704
637 foreach (IScriptInstance i in instances) 705 foreach (IScriptInstance i in instances)
638 { 706 {
639 string assembly = String.Empty; 707 string assembly = String.Empty;
640 708
641 lock (m_Scripts) 709
642 {
643 if (!m_Assemblies.ContainsKey(i.AssetID)) 710 if (!m_Assemblies.ContainsKey(i.AssetID))
644 continue; 711 continue;
645 assembly = m_Assemblies[i.AssetID]; 712 assembly = m_Assemblies[i.AssetID];
646 } 713
647 714
648 i.SaveState(assembly); 715 i.SaveState(assembly);
649 } 716 }
@@ -987,91 +1054,95 @@ namespace OpenSim.Region.ScriptEngine.XEngine
987 } 1054 }
988 1055
989 ScriptInstance instance = null; 1056 ScriptInstance instance = null;
990 lock (m_Scripts) 1057 // Create the object record
1058 lockScriptsForRead(true);
1059 if ((!m_Scripts.ContainsKey(itemID)) ||
1060 (m_Scripts[itemID].AssetID != assetID))
991 { 1061 {
992 // Create the object record 1062 lockScriptsForRead(false);
993 if ((!m_Scripts.ContainsKey(itemID)) ||
994 (m_Scripts[itemID].AssetID != assetID))
995 {
996 UUID appDomain = assetID;
997 1063
998 if (part.ParentGroup.IsAttachment) 1064 UUID appDomain = assetID;
999 appDomain = part.ParentGroup.RootPart.UUID;
1000 1065
1001 if (!m_AppDomains.ContainsKey(appDomain)) 1066 if (part.ParentGroup.IsAttachment)
1002 { 1067 appDomain = part.ParentGroup.RootPart.UUID;
1003 try
1004 {
1005 AppDomainSetup appSetup = new AppDomainSetup();
1006 appSetup.PrivateBinPath = Path.Combine(
1007 m_ScriptEnginesPath,
1008 m_Scene.RegionInfo.RegionID.ToString());
1009
1010 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
1011 Evidence evidence = new Evidence(baseEvidence);
1012
1013 AppDomain sandbox;
1014 if (m_AppDomainLoading)
1015 sandbox = AppDomain.CreateDomain(
1016 m_Scene.RegionInfo.RegionID.ToString(),
1017 evidence, appSetup);
1018 else
1019 sandbox = AppDomain.CurrentDomain;
1020
1021 //PolicyLevel sandboxPolicy = PolicyLevel.CreateAppDomainLevel();
1022 //AllMembershipCondition sandboxMembershipCondition = new AllMembershipCondition();
1023 //PermissionSet sandboxPermissionSet = sandboxPolicy.GetNamedPermissionSet("Internet");
1024 //PolicyStatement sandboxPolicyStatement = new PolicyStatement(sandboxPermissionSet);
1025 //CodeGroup sandboxCodeGroup = new UnionCodeGroup(sandboxMembershipCondition, sandboxPolicyStatement);
1026 //sandboxPolicy.RootCodeGroup = sandboxCodeGroup;
1027 //sandbox.SetAppDomainPolicy(sandboxPolicy);
1028
1029 m_AppDomains[appDomain] = sandbox;
1030 1068
1031 m_AppDomains[appDomain].AssemblyResolve += 1069 if (!m_AppDomains.ContainsKey(appDomain))
1032 new ResolveEventHandler( 1070 {
1033 AssemblyResolver.OnAssemblyResolve); 1071 try
1034 m_DomainScripts[appDomain] = new List<UUID>(); 1072 {
1035 } 1073 AppDomainSetup appSetup = new AppDomainSetup();
1036 catch (Exception e) 1074 appSetup.PrivateBinPath = Path.Combine(
1075 m_ScriptEnginesPath,
1076 m_Scene.RegionInfo.RegionID.ToString());
1077
1078 Evidence baseEvidence = AppDomain.CurrentDomain.Evidence;
1079 Evidence evidence = new Evidence(baseEvidence);
1080
1081 AppDomain sandbox;
1082 if (m_AppDomainLoading)
1083 sandbox = AppDomain.CreateDomain(
1084 m_Scene.RegionInfo.RegionID.ToString(),
1085 evidence, appSetup);
1086 else
1087 sandbox = AppDomain.CurrentDomain;
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
1099 m_AppDomains[appDomain].AssemblyResolve +=
1100 new ResolveEventHandler(
1101 AssemblyResolver.OnAssemblyResolve);
1102 m_DomainScripts[appDomain] = new List<UUID>();
1103 }
1104 catch (Exception e)
1105 {
1106 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString());
1107 m_ScriptErrorMessage += "Exception creating app domain:\n";
1108 m_ScriptFailCount++;
1109 lock (m_AddingAssemblies)
1037 { 1110 {
1038 m_log.ErrorFormat("[XEngine] Exception creating app domain:\n {0}", e.ToString()); 1111 m_AddingAssemblies[assembly]--;
1039 m_ScriptErrorMessage += "Exception creating app domain:\n";
1040 m_ScriptFailCount++;
1041 lock (m_AddingAssemblies)
1042 {
1043 m_AddingAssemblies[assembly]--;
1044 }
1045 return false;
1046 } 1112 }
1113 return false;
1047 } 1114 }
1048 m_DomainScripts[appDomain].Add(itemID); 1115 }
1049 1116 m_DomainScripts[appDomain].Add(itemID);
1050 instance = new ScriptInstance(this, part, 1117
1051 itemID, assetID, assembly, 1118 instance = new ScriptInstance(this, part,
1052 m_AppDomains[appDomain], 1119 itemID, assetID, assembly,
1053 part.ParentGroup.RootPart.Name, 1120 m_AppDomains[appDomain],
1054 item.Name, startParam, postOnRez, 1121 part.ParentGroup.RootPart.Name,
1055 stateSource, m_MaxScriptQueue); 1122 item.Name, startParam, postOnRez,
1056 1123 stateSource, m_MaxScriptQueue);
1057 m_log.DebugFormat( 1124
1058 "[XEngine] Loaded script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", 1125 m_log.DebugFormat(
1059 part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, 1126 "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}",
1127 part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID,
1060 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); 1128 part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName);
1061 1129
1062 if (presence != null) 1130 if (presence != null)
1063 { 1131 {
1064 ShowScriptSaveResponse(item.OwnerID, 1132 ShowScriptSaveResponse(item.OwnerID,
1065 assetID, "Compile successful", true); 1133 assetID, "Compile successful", true);
1066 }
1067
1068 instance.AppDomain = appDomain;
1069 instance.LineMap = linemap;
1070
1071 m_Scripts[itemID] = instance;
1072 } 1134 }
1073 }
1074 1135
1136 instance.AppDomain = appDomain;
1137 instance.LineMap = linemap;
1138 lockScriptsForWrite(true);
1139 m_Scripts[itemID] = instance;
1140 lockScriptsForWrite(false);
1141 }
1142 else
1143 {
1144 lockScriptsForRead(false);
1145 }
1075 lock (m_PrimObjects) 1146 lock (m_PrimObjects)
1076 { 1147 {
1077 if (!m_PrimObjects.ContainsKey(localID)) 1148 if (!m_PrimObjects.ContainsKey(localID))
@@ -1090,9 +1161,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1090 m_AddingAssemblies[assembly]--; 1161 m_AddingAssemblies[assembly]--;
1091 } 1162 }
1092 1163
1093 if (instance != null) 1164 if (instance!=null)
1094 instance.Init(); 1165 instance.Init();
1095 1166
1096 return true; 1167 return true;
1097 } 1168 }
1098 1169
@@ -1105,20 +1176,31 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1105 m_CompileDict.Remove(itemID); 1176 m_CompileDict.Remove(itemID);
1106 } 1177 }
1107 1178
1108 IScriptInstance instance = null; 1179 lockScriptsForRead(true);
1109 1180 // Do we even have it?
1110 lock (m_Scripts) 1181 if (!m_Scripts.ContainsKey(itemID))
1111 { 1182 {
1112 // Do we even have it? 1183 // Do we even have it?
1113 if (!m_Scripts.ContainsKey(itemID)) 1184 if (!m_Scripts.ContainsKey(itemID))
1114 return; 1185 return;
1115 1186
1116 instance = m_Scripts[itemID]; 1187 lockScriptsForRead(false);
1188 lockScriptsForWrite(true);
1117 m_Scripts.Remove(itemID); 1189 m_Scripts.Remove(itemID);
1190 lockScriptsForWrite(false);
1191
1192 return;
1118 } 1193 }
1194
1119 1195
1196 IScriptInstance instance=m_Scripts[itemID];
1197 lockScriptsForRead(false);
1198 lockScriptsForWrite(true);
1199 m_Scripts.Remove(itemID);
1200 lockScriptsForWrite(false);
1120 instance.ClearQueue(); 1201 instance.ClearQueue();
1121 instance.Stop(0); 1202 instance.Stop(0);
1203
1122// bool objectRemoved = false; 1204// bool objectRemoved = false;
1123 1205
1124 lock (m_PrimObjects) 1206 lock (m_PrimObjects)
@@ -1154,10 +1236,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1154 ObjectRemoved handlerObjectRemoved = OnObjectRemoved; 1236 ObjectRemoved handlerObjectRemoved = OnObjectRemoved;
1155 if (handlerObjectRemoved != null) 1237 if (handlerObjectRemoved != null)
1156 { 1238 {
1157 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID); 1239 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
1158 handlerObjectRemoved(part.UUID); 1240 handlerObjectRemoved(part.UUID);
1159 } 1241 }
1160 1242
1243 CleanAssemblies();
1244
1161 ScriptRemoved handlerScriptRemoved = OnScriptRemoved; 1245 ScriptRemoved handlerScriptRemoved = OnScriptRemoved;
1162 if (handlerScriptRemoved != null) 1246 if (handlerScriptRemoved != null)
1163 handlerScriptRemoved(itemID); 1247 handlerScriptRemoved(itemID);
@@ -1299,7 +1383,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1299 return false; 1383 return false;
1300 1384
1301 uuids = m_PrimObjects[localID]; 1385 uuids = m_PrimObjects[localID];
1302 } 1386
1303 1387
1304 foreach (UUID itemID in uuids) 1388 foreach (UUID itemID in uuids)
1305 { 1389 {
@@ -1317,6 +1401,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1317 result = true; 1401 result = true;
1318 } 1402 }
1319 } 1403 }
1404 }
1320 1405
1321 return result; 1406 return result;
1322 } 1407 }
@@ -1418,12 +1503,14 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1418 private IScriptInstance GetInstance(UUID itemID) 1503 private IScriptInstance GetInstance(UUID itemID)
1419 { 1504 {
1420 IScriptInstance instance; 1505 IScriptInstance instance;
1421 lock (m_Scripts) 1506 lockScriptsForRead(true);
1507 if (!m_Scripts.ContainsKey(itemID))
1422 { 1508 {
1423 if (!m_Scripts.ContainsKey(itemID)) 1509 lockScriptsForRead(false);
1424 return null; 1510 return null;
1425 instance = m_Scripts[itemID];
1426 } 1511 }
1512 instance = m_Scripts[itemID];
1513 lockScriptsForRead(false);
1427 return instance; 1514 return instance;
1428 } 1515 }
1429 1516
@@ -1447,6 +1534,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1447 return false; 1534 return false;
1448 } 1535 }
1449 1536
1537 [DebuggerNonUserCode]
1450 public void ApiResetScript(UUID itemID) 1538 public void ApiResetScript(UUID itemID)
1451 { 1539 {
1452 IScriptInstance instance = GetInstance(itemID); 1540 IScriptInstance instance = GetInstance(itemID);
@@ -1498,6 +1586,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1498 return UUID.Zero; 1586 return UUID.Zero;
1499 } 1587 }
1500 1588
1589 [DebuggerNonUserCode]
1501 public void SetState(UUID itemID, string newState) 1590 public void SetState(UUID itemID, string newState)
1502 { 1591 {
1503 IScriptInstance instance = GetInstance(itemID); 1592 IScriptInstance instance = GetInstance(itemID);
@@ -1520,11 +1609,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1520 1609
1521 List<IScriptInstance> instances = new List<IScriptInstance>(); 1610 List<IScriptInstance> instances = new List<IScriptInstance>();
1522 1611
1523 lock (m_Scripts) 1612 lockScriptsForRead(true);
1524 { 1613 foreach (IScriptInstance instance in m_Scripts.Values)
1525 foreach (IScriptInstance instance in m_Scripts.Values)
1526 instances.Add(instance); 1614 instances.Add(instance);
1527 } 1615 lockScriptsForRead(false);
1528 1616
1529 foreach (IScriptInstance i in instances) 1617 foreach (IScriptInstance i in instances)
1530 { 1618 {
@@ -1909,5 +1997,17 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1909// else 1997// else
1910// m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID); 1998// m_log.DebugFormat("[XEngine]: Could not find script with ID {0} to resume", itemID);
1911 } 1999 }
2000
2001 public bool HasScript(UUID itemID, out bool running)
2002 {
2003 running = true;
2004
2005 IScriptInstance instance = GetInstance(itemID);
2006 if (instance == null)
2007 return false;
2008
2009 running = instance.Running;
2010 return true;
2011 }
1912 } 2012 }
1913} \ No newline at end of file 2013}